diff options
author | Vitaly Buka <vitalybuka@google.com> | 2023-12-12 17:07:42 -0800 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2023-12-12 17:07:42 -0800 |
commit | 79b7f3fd24ab19e9272eddd8d0f2b39d893222c9 (patch) | |
tree | 22871065c49d77394007a1999e8855e49783716b | |
parent | 2dad66c39ce65a06df39cd761362624b355951e3 (diff) | |
parent | dd9587795811ba21e6ca6ad52b4531e17e6babd6 (diff) | |
download | llvm-79b7f3fd24ab19e9272eddd8d0f2b39d893222c9.zip llvm-79b7f3fd24ab19e9272eddd8d0f2b39d893222c9.tar.gz llvm-79b7f3fd24ab19e9272eddd8d0f2b39d893222c9.tar.bz2 |
[𝘀𝗽𝗿] changes introduced through rebase
Created using spr 1.3.4
[skip ci]
85 files changed, 1320 insertions, 1043 deletions
diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp index 2264c55..0526384 100644 --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/fork_threaded.cpp @@ -18,10 +18,10 @@ static const size_t kBufferSize = 1 << 20; -static void *background(void *arg) { return nullptr; } - pthread_barrier_t bar; +// Without appropriate workarounds this code can cause the forked process to +// start with locked internal mutexes. void CanDeadLock() { // Don't bother with leaks, we try to trigger allocator or lsan deadlock. __lsan::ScopedDisabler disable; diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 2973ee0..f4973cd 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -415,70 +415,19 @@ public: void FindGlobalVariables(const RegularExpression ®ex, size_t max_matches, VariableList &variable_list); - /// Find types by name. - /// - /// Type lookups in modules go through the SymbolFile. The SymbolFile needs to - /// be able to lookup types by basename and not the fully qualified typename. - /// This allows the type accelerator tables to stay small, even with heavily - /// templatized C++. The type search will then narrow down the search - /// results. If "exact_match" is true, then the type search will only match - /// exact type name matches. If "exact_match" is false, the type will match - /// as long as the base typename matches and as long as any immediate - /// containing namespaces/class scopes that are specified match. So to - /// search for a type "d" in "b::c", the name "b::c::d" can be specified and - /// it will match any class/namespace "b" which contains a class/namespace - /// "c" which contains type "d". We do this to allow users to not always - /// have to specify complete scoping on all expressions, but it also allows - /// for exact matching when required. - /// - /// \param[in] type_name - /// The name of the type we are looking for that is a fully - /// or partially qualified type name. - /// - /// \param[in] exact_match - /// If \b true, \a type_name is fully qualified and must match - /// exactly. If \b false, \a type_name is a partially qualified - /// name where the leading namespaces or classes can be - /// omitted to make finding types that a user may type - /// easier. - /// - /// \param[out] types - /// A type list gets populated with any matches. + /// Find types using a type-matching object that contains all search + /// parameters. /// - void - FindTypes(ConstString type_name, bool exact_match, size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeList &types); - - /// Find types by name. - /// - /// This behaves like the other FindTypes method but allows to - /// specify a DeclContext and a language for the type being searched - /// for. - /// - /// \param searched_symbol_files - /// Prevents one file from being visited multiple times. - void - FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types); - - lldb::TypeSP FindFirstType(const SymbolContext &sc, ConstString type_name, - bool exact_match); - - /// Find types by name that are in a namespace. This function is used by the - /// expression parser when searches need to happen in an exact namespace - /// scope. + /// \see lldb_private::TypeQuery /// - /// \param[in] type_name - /// The name of a type within a namespace that should not include - /// any qualifying namespaces (just a type basename). + /// \param[in] query + /// A type matching object that contains all of the details of the type + /// search. /// - /// \param[out] type_list - /// A type list gets populated with any matches. - void FindTypesInNamespace(ConstString type_name, - const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, TypeList &type_list); + /// \param[in] results + /// Any matching types will be populated into the \a results object using + /// TypeMap::InsertUnique(...). + void FindTypes(const TypeQuery &query, TypeResults &results); /// Get const accessor for the module architecture. /// @@ -1122,12 +1071,6 @@ protected: private: Module(); // Only used internally by CreateJITModule () - void FindTypes_Impl( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types); - Module(const Module &) = delete; const Module &operator=(const Module &) = delete; diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 9826dd0..d78f7c5 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -340,26 +340,22 @@ public: lldb::SymbolType symbol_type, SymbolContextList &sc_list) const; - /// Find types by name. + /// Find types using a type-matching object that contains all search + /// parameters. /// /// \param[in] search_first /// If non-null, this module will be searched before any other /// modules. /// - /// \param[in] name - /// The name of the type we are looking for. - /// - /// \param[in] max_matches - /// Allow the number of matches to be limited to \a - /// max_matches. Specify UINT32_MAX to get all possible matches. - /// - /// \param[out] types - /// A type list gets populated with any matches. + /// \param[in] query + /// A type matching object that contains all of the details of the type + /// search. /// - void FindTypes(Module *search_first, ConstString name, - bool name_is_fully_qualified, size_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeList &types) const; + /// \param[in] results + /// Any matching types will be populated into the \a results object using + /// TypeMap::InsertUnique(...). + void FindTypes(Module *search_first, const TypeQuery &query, + lldb_private::TypeResults &results) const; bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const; diff --git a/lldb/include/lldb/Symbol/CompilerDecl.h b/lldb/include/lldb/Symbol/CompilerDecl.h index 67290b9..825a4f1 100644 --- a/lldb/include/lldb/Symbol/CompilerDecl.h +++ b/lldb/include/lldb/Symbol/CompilerDecl.h @@ -84,6 +84,13 @@ public: // based argument index CompilerType GetFunctionArgumentType(size_t arg_idx) const; + /// Populate a valid compiler context from the current declaration. + /// + /// \returns A valid vector of CompilerContext entries that describes + /// this declaration. The first entry in the vector is the parent of + /// the subsequent entry, so the topmost entry is the global namespace. + std::vector<lldb_private::CompilerContext> GetCompilerContext() const; + private: TypeSystem *m_type_system = nullptr; void *m_opaque_decl = nullptr; diff --git a/lldb/include/lldb/Symbol/CompilerDeclContext.h b/lldb/include/lldb/Symbol/CompilerDeclContext.h index 61a9c9c..89b4a97 100644 --- a/lldb/include/lldb/Symbol/CompilerDeclContext.h +++ b/lldb/include/lldb/Symbol/CompilerDeclContext.h @@ -11,6 +11,7 @@ #include <vector> +#include "lldb/Symbol/Type.h" #include "lldb/Utility/ConstString.h" #include "lldb/lldb-private.h" @@ -56,6 +57,13 @@ public: return m_type_system != nullptr && m_opaque_decl_ctx != nullptr; } + /// Populate a valid compiler context from the current decl context. + /// + /// \returns A valid vector of CompilerContext entries that describes + /// this declaration context. The first entry in the vector is the parent of + /// the subsequent entry, so the topmost entry is the global namespace. + std::vector<lldb_private::CompilerContext> GetCompilerContext() const; + std::vector<CompilerDecl> FindDeclByName(ConstString name, const bool ignore_using_decls); diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index a546b05..c9a2a64 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -301,21 +301,20 @@ public: bool include_inlines, SymbolContextList &sc_list); virtual void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list); - virtual void - FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types); - - /// Find types specified by a CompilerContextPattern. - /// \param languages - /// Only return results in these languages. - /// \param searched_symbol_files - /// Prevents one file from being visited multiple times. - virtual void - FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types); + + /// Find types using a type-matching object that contains all search + /// parameters. + /// + /// \see lldb_private::TypeQuery + /// + /// \param[in] query + /// A type matching object that contains all of the details of the type + /// search. + /// + /// \param[in] results + /// Any matching types will be populated into the \a results object using + /// TypeMap::InsertUnique(...). + virtual void FindTypes(const TypeQuery &query, TypeResults &results) {} virtual void GetMangledNamesForFunction(const std::string &scope_qualified_name, diff --git a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h index 9cbcef2..cde9f3c 100644 --- a/lldb/include/lldb/Symbol/SymbolFileOnDemand.h +++ b/lldb/include/lldb/Symbol/SymbolFileOnDemand.h @@ -152,17 +152,8 @@ public: const std::string &scope_qualified_name, std::vector<lldb_private::ConstString> &mangled_names) override; - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, - lldb_private::LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &query, + lldb_private::TypeResults &results) override; void GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 15edbea..307be6c 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -12,11 +12,15 @@ #include "lldb/Core/Declaration.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/TypeList.h" +#include "lldb/Symbol/TypeMap.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" #include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseSet.h" #include <optional> #include <set> @@ -24,6 +28,23 @@ namespace lldb_private { class SymbolFileCommon; +/// A SmallBitVector that represents a set of source languages (\p +/// lldb::LanguageType). Each lldb::LanguageType is represented by +/// the bit with the position of its enumerator. The largest +/// LanguageType is < 64, so this is space-efficient and on 64-bit +/// architectures a LanguageSet can be completely stack-allocated. +struct LanguageSet { + llvm::SmallBitVector bitvector; + LanguageSet(); + + /// If the set contains a single language only, return it. + std::optional<lldb::LanguageType> GetSingularLanguage(); + void Insert(lldb::LanguageType language); + bool Empty() const; + size_t Size() const; + bool operator[](unsigned i) const; +}; + /// CompilerContext allows an array of these items to be passed to perform /// detailed lookups in SymbolVendor and SymbolFile functions. struct CompilerContext { @@ -45,6 +66,290 @@ struct CompilerContext { bool contextMatches(llvm::ArrayRef<CompilerContext> context_chain, llvm::ArrayRef<CompilerContext> pattern); +FLAGS_ENUM(TypeQueryOptions){ + e_none = 0u, + /// If set, TypeQuery::m_context contains an exact context that must match + /// the full context. If not set, TypeQuery::m_context can contain a partial + /// type match where the full context isn't fully specified. + e_exact_match = (1u << 0), + /// If set, TypeQuery::m_context is a clang module compiler context. If not + /// set TypeQuery::m_context is normal type lookup context. + e_module_search = (1u << 1), + /// When true, the find types call should stop the query as soon as a single + /// matching type is found. When false, the type query should find all + /// matching types. + e_find_one = (1u << 2), +}; +LLDB_MARK_AS_BITMASK_ENUM(TypeQueryOptions) + +/// A class that contains all state required for type lookups. +/// +/// Using a TypeQuery class for matching types simplifies the internal APIs we +/// need to implement type lookups in LLDB. Type lookups can fully specify the +/// exact typename by filling out a complete or partial CompilerContext array. +/// This technique allows for powerful searches and also allows the SymbolFile +/// classes to use the m_context array to lookup types by basename, then +/// eliminate potential matches without having to resolve types into each +/// TypeSystem. This makes type lookups vastly more efficient and allows the +/// SymbolFile objects to stop looking up types when the type matching is +/// complete, like if we are looking for only a single type in our search. +class TypeQuery { +public: + TypeQuery() = delete; + + /// Construct a type match object using a fully- or partially-qualified name. + /// + /// The specified \a type_name will be chopped up and the m_context will be + /// populated by separating the string by looking for "::". We do this because + /// symbol files have indexes that contain only the type's basename. This also + /// allows symbol files to efficiently not realize types that don't match the + /// specified context. Example of \a type_name values that can be specified + /// include: + /// "foo": Look for any type whose basename matches "foo". + /// If \a exact_match is true, then the type can't be contained in any + /// declaration context like a namespace, class, or other containing + /// scope. + /// If \a exact match is false, then we will find all matches including + /// ones that are contained in other declaration contexts, including top + /// level types. + /// "foo::bar": Look for any type whose basename matches "bar" but make sure + /// its parent declaration context is any named declaration context + /// (namespace, class, struct, etc) whose name matches "foo". + /// If \a exact_match is true, then the "foo" declaration context must + /// appear at the source file level or inside of a function. + /// If \a exact match is false, then the "foo" declaration context can + /// be contained in any other declaration contexts. + /// "class foo": Only match types that are classes whose basename matches + /// "foo". + /// "struct foo": Only match types that are structures whose basename + /// matches "foo". + /// "class foo::bar": Only match types that are classes whose basename + /// matches "bar" and that are contained in any named declaration context + /// named "foo". + /// + /// \param[in] type_name + /// A fully- or partially-qualified type name. This name will be parsed and + /// broken up and the m_context will be populated with the various parts of + /// the name. This typename can be prefixed with "struct ", "class ", + /// "union", "enum " or "typedef " before the actual type name to limit the + /// results of the types that match. The declaration context can be + /// specified with the "::" string. For example, "a::b::my_type". + /// + /// \param[in] options A set of boolean enumeration flags from the + /// TypeQueryOptions enumerations. \see TypeQueryOptions. + TypeQuery(llvm::StringRef name, TypeQueryOptions options = e_none); + + /// Construct a type-match object that matches a type basename that exists + /// in the specified declaration context. + /// + /// This allows the m_context to be first populated using a declaration + /// context to exactly identify the containing declaration context of a type. + /// This can be used when you have a forward declaration to a type and you + /// need to search for its complete type. + /// + /// \param[in] decl_ctx + /// A declaration context object that comes from a TypeSystem plug-in. This + /// object will be asked to populate the array of CompilerContext objects + /// by adding the top most declaration context first into the array and then + /// adding any containing declaration contexts. + /// + /// \param[in] type_basename + /// The basename of the type to lookup in the specified declaration context. + /// + /// \param[in] options A set of boolean enumeration flags from the + /// TypeQueryOptions enumerations. \see TypeQueryOptions. + TypeQuery(const CompilerDeclContext &decl_ctx, ConstString type_basename, + TypeQueryOptions options = e_none); + /// Construct a type-match object using a compiler declaration that specifies + /// a typename and a declaration context to use when doing exact type lookups. + /// + /// This allows the m_context to be first populated using a type declaration. + /// The type declaration might have a declaration context and each TypeSystem + /// plug-in can populate the declaration context needed to perform an exact + /// lookup for a type. + /// This can be used when you have a forward declaration to a type and you + /// need to search for its complete type. + /// + /// \param[in] decl + /// A type declaration context object that comes from a TypeSystem plug-in. + /// This object will be asked to full the array of CompilerContext objects + /// by adding the top most declaration context first into the array and then + /// adding any containing declaration contexts, and ending with the exact + /// typename and the kind of type it is (class, struct, union, enum, etc). + /// + /// \param[in] options A set of boolean enumeration flags from the + /// TypeQueryOptions enumerations. \see TypeQueryOptions. + TypeQuery(const CompilerDecl &decl, TypeQueryOptions options = e_none); + + /// Construct a type-match object using a CompilerContext array. + /// + /// Clients can manually create compiler contexts and use these to find + /// matches when searching for types. There are two types of contexts that + /// are supported when doing type searchs: type contexts and clang module + /// contexts. Type contexts have contexts that specify the type and its + /// containing declaration context like namespaces and classes. Clang module + /// contexts specify contexts more completely to find exact matches within + /// clang module debug information. They will include the modules that the + /// type is included in and any functions that the type might be defined in. + /// This allows very fine-grained type resolution. + /// + /// \param[in] context The compiler context to use when doing the search. + /// + /// \param[in] options A set of boolean enumeration flags from the + /// TypeQueryOptions enumerations. \see TypeQueryOptions. + TypeQuery(const llvm::ArrayRef<lldb_private::CompilerContext> &context, + TypeQueryOptions options = e_none); + + /// Construct a type-match object that duplicates all matching criterea, + /// but not any searched symbol files or the type map for matches. This allows + /// the m_context to be modified prior to performing another search. + TypeQuery(const TypeQuery &rhs) = default; + /// Assign a type-match object that duplicates all matching criterea, + /// but not any searched symbol files or the type map for matches. This allows + /// the m_context to be modified prior to performing another search. + TypeQuery &operator=(const TypeQuery &rhs) = default; + + /// Check of a CompilerContext array from matching type from a symbol file + /// matches the \a m_context. + /// + /// \param[in] context + /// A fully qualified CompilerContext array for a potential match that is + /// created by the symbol file prior to trying to actually resolve a type. + /// + /// \returns + /// True if the context matches, false if it doesn't. If e_exact_match + /// is set in m_options, then \a context must exactly match \a m_context. If + /// e_exact_match is not set, then the bottom m_context.size() objects in + /// \a context must match. This allows SymbolFile objects the fill in a + /// potential type basename match from the index into \a context, and see if + /// it matches prior to having to resolve a lldb_private::Type object for + /// the type from the index. This allows type parsing to be as efficient as + /// possible and only realize the types that match the query. + bool + ContextMatches(llvm::ArrayRef<lldb_private::CompilerContext> context) const; + + /// Get the type basename to use when searching the type indexes in each + /// SymbolFile object. + /// + /// Debug information indexes often contain indexes that track the basename + /// of types only, not a fully qualified path. This allows the indexes to be + /// smaller and allows for efficient lookups. + /// + /// \returns + /// The type basename to use when doing lookups as a constant string. + ConstString GetTypeBasename() const; + + /// Returns true if any matching languages have been specified in this type + /// matching object. + bool HasLanguage() const { return m_languages.has_value(); } + + /// Add a language family to the list of languages that should produce a + /// match. + void AddLanguage(lldb::LanguageType language); + + /// Check if the language matches any languages that have been added to this + /// match object. + /// + /// \returns + /// True if no language have been specified, or if some language have been + /// added using AddLanguage(...) and they match. False otherwise. + bool LanguageMatches(lldb::LanguageType language) const; + + bool GetExactMatch() const { return (m_options & e_exact_match) != 0; } + /// The \a m_context can be used in two ways: normal types searching with + /// the context containing a stanadard declaration context for a type, or + /// with the context being more complete for exact matches in clang modules. + /// Set this to true if you wish to search for a type in clang module. + bool GetModuleSearch() const { return (m_options & e_module_search) != 0; } + + /// Returns true if the type query is supposed to find only a single matching + /// type. Returns false if the type query should find all matches. + bool GetFindOne() const { return (m_options & e_find_one) != 0; } + void SetFindOne(bool b) { + if (b) + m_options |= e_find_one; + else + m_options &= (e_exact_match | e_find_one); + } + + /// Access the internal compiler context array. + /// + /// Clients can use this to populate the context manually. + std::vector<lldb_private::CompilerContext> &GetContextRef() { + return m_context; + } + +protected: + /// A full or partial compiler context array where the parent declaration + /// contexts appear at the top of the array starting at index zero and the + /// last entry contains the type and name of the type we are looking for. + std::vector<lldb_private::CompilerContext> m_context; + /// An options bitmask that contains enabled options for the type query. + /// \see TypeQueryOptions. + TypeQueryOptions m_options; + /// If this variable has a value, then the language family must match at least + /// one of the specified languages. If this variable has no value, then the + /// language of the type doesn't need to match any types that are searched. + std::optional<LanguageSet> m_languages; +}; + +/// This class tracks the state and results of a \ref TypeQuery. +/// +/// Any mutable state required for type lookups and the results are tracked in +/// this object. +class TypeResults { +public: + /// Construct a type results object + TypeResults() = default; + + /// When types that match a TypeQuery are found, this API is used to insert + /// the matching types. + /// + /// \return + /// True if the type was added, false if the \a type_sp was already in the + /// results. + bool InsertUnique(const lldb::TypeSP &type_sp); + + /// Check if the type matching has found all of the matches that it needs. + bool Done(const TypeQuery &query) const; + + /// Check if a SymbolFile object has already been searched by this type match + /// object. + /// + /// This function will add \a sym_file to the set of SymbolFile objects if it + /// isn't already in the set and return \a false. Returns true if \a sym_file + /// was already in the set and doesn't need to be searched. + /// + /// Any clients that search for types should first check that the symbol file + /// has not already been searched. If this function returns true, the type + /// search function should early return to avoid duplicating type searchihng + /// efforts. + /// + /// \param[in] sym_file + /// A SymbolFile pointer that will be used to track which symbol files have + /// already been searched. + /// + /// \returns + /// True if the symbol file has been search already, false otherwise. + bool AlreadySearched(lldb_private::SymbolFile *sym_file); + + /// Access the set of searched symbol files. + llvm::DenseSet<lldb_private::SymbolFile *> &GetSearchedSymbolFiles() { + return m_searched_symbol_files; + } + + lldb::TypeSP GetFirstType() const { return m_type_map.FirstType(); } + TypeMap &GetTypeMap() { return m_type_map; } + const TypeMap &GetTypeMap() const { return m_type_map; } + +private: + /// Matching types get added to this map as type search continues. + TypeMap m_type_map; + /// This set is used to track and make sure we only perform lookups in a + /// symbol file one time. + llvm::DenseSet<lldb_private::SymbolFile *> m_searched_symbol_files; +}; + class SymbolFileType : public std::enable_shared_from_this<SymbolFileType>, public UserID { public: diff --git a/lldb/include/lldb/Symbol/TypeMap.h b/lldb/include/lldb/Symbol/TypeMap.h index c200ccb..4337118 100644 --- a/lldb/include/lldb/Symbol/TypeMap.h +++ b/lldb/include/lldb/Symbol/TypeMap.h @@ -27,7 +27,7 @@ public: void Clear(); void Dump(Stream *s, bool show_context, - lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) const; TypeMap FindTypes(ConstString name); @@ -41,10 +41,12 @@ public: lldb::TypeSP GetTypeAtIndex(uint32_t idx); + lldb::TypeSP FirstType() const; + typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection; typedef AdaptedIterable<collection, lldb::TypeSP, map_adapter> TypeIterable; - TypeIterable Types() { return TypeIterable(m_types); } + TypeIterable Types() const { return TypeIterable(m_types); } void ForEach( std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const; diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index cd5004a..6382913 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -26,6 +26,7 @@ #include "lldb/Expression/Expression.h" #include "lldb/Symbol/CompilerDecl.h" #include "lldb/Symbol/CompilerDeclContext.h" +#include "lldb/Symbol/Type.h" #include "lldb/lldb-private.h" class PDBASTParser; @@ -43,23 +44,6 @@ namespace npdb { class PdbAstBuilder; } // namespace npdb -/// A SmallBitVector that represents a set of source languages (\p -/// lldb::LanguageType). Each lldb::LanguageType is represented by -/// the bit with the position of its enumerator. The largest -/// LanguageType is < 64, so this is space-efficient and on 64-bit -/// architectures a LanguageSet can be completely stack-allocated. -struct LanguageSet { - llvm::SmallBitVector bitvector; - LanguageSet(); - - /// If the set contains a single language only, return it. - std::optional<lldb::LanguageType> GetSingularLanguage(); - void Insert(lldb::LanguageType language); - bool Empty() const; - size_t Size() const; - bool operator[](unsigned i) const; -}; - /// Interface for representing a type system. /// /// Implemented by language plugins to define the type system for a given @@ -122,6 +106,9 @@ public: virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl, size_t arg_idx); + virtual std::vector<lldb_private::CompilerContext> + DeclGetCompilerContext(void *opaque_decl); + virtual CompilerType GetTypeForDecl(void *opaque_decl) = 0; // CompilerDeclContext functions @@ -146,6 +133,9 @@ public: virtual CompilerDeclContext GetCompilerDeclContextForType(const CompilerType &type); + virtual std::vector<lldb_private::CompilerContext> + DeclContextGetCompilerContext(void *opaque_decl_ctx); + // Tests #ifndef NDEBUG /// Verify the integrity of the type to catch CompilerTypes that mix diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 068fce4..4e0c62f 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -258,9 +258,11 @@ class TypeImpl; class TypeList; class TypeListImpl; class TypeMap; +class TypeQuery; class TypeMemberFunctionImpl; class TypeMemberImpl; class TypeNameSpecifierImpl; +class TypeResults; class TypeSummaryImpl; class TypeSummaryOptions; class TypeSystem; diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h index 7f98220..5f15972 100644 --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -198,12 +198,15 @@ enum class CompilerContextKind : uint16_t { Variable = 1 << 7, Enum = 1 << 8, Typedef = 1 << 9, + Builtin = 1 << 10, Any = 1 << 15, /// Match 0..n nested modules. AnyModule = Any | Module, /// Match any type. - AnyType = Any | Class | Struct | Union | Enum | Typedef + AnyType = Any | Class | Struct | Union | Enum | Typedef | Builtin, + /// Math any declaration context. + AnyDeclContext = Any | Namespace | Class | Struct | Union | Enum | Function }; // Enumerations that can be used to specify the kind of metric we're looking at diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index b865502..262e26c 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -437,26 +437,25 @@ lldb::SBType SBModule::FindFirstType(const char *name_cstr) { LLDB_INSTRUMENT_VA(this, name_cstr); ModuleSP module_sp(GetSP()); - if (!name_cstr || !module_sp) - return {}; - SymbolContext sc; - const bool exact_match = false; - ConstString name(name_cstr); + if (name_cstr && module_sp) { + ConstString name(name_cstr); + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_find_one); + TypeResults results; + module_sp->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return SBType(type_sp); - SBType sb_type = SBType(module_sp->FindFirstType(sc, name, exact_match)); - - if (sb_type.IsValid()) - return sb_type; + auto type_system_or_err = + module_sp->GetTypeSystemForLanguage(eLanguageTypeC); + if (auto err = type_system_or_err.takeError()) { + llvm::consumeError(std::move(err)); + return {}; + } - auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); - if (auto err = type_system_or_err.takeError()) { - llvm::consumeError(std::move(err)); - return {}; + if (auto ts = *type_system_or_err) + return SBType(ts->GetBuiltinTypeByName(name)); } - - if (auto ts = *type_system_or_err) - return SBType(ts->GetBuiltinTypeByName(name)); - return {}; } @@ -471,7 +470,7 @@ lldb::SBType SBModule::GetBasicType(lldb::BasicType type) { llvm::consumeError(std::move(err)); } else { if (auto ts = *type_system_or_err) - return SBType(ts->GetBasicTypeFromAST(type)); + return SBType(ts->GetBasicTypeFromAST(type)); } } return SBType(); @@ -485,13 +484,11 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { ModuleSP module_sp(GetSP()); if (type && module_sp) { TypeList type_list; - const bool exact_match = false; - ConstString name(type); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_sp->FindTypes(name, exact_match, UINT32_MAX, searched_symbol_files, - type_list); - - if (type_list.Empty()) { + TypeQuery query(type); + TypeResults results; + module_sp->FindTypes(query, results); + if (results.GetTypeMap().Empty()) { + ConstString name(type); auto type_system_or_err = module_sp->GetTypeSystemForLanguage(eLanguageTypeC); if (auto err = type_system_or_err.takeError()) { @@ -502,11 +499,8 @@ lldb::SBTypeList SBModule::FindTypes(const char *type) { retval.Append(SBType(compiler_type)); } } else { - for (size_t idx = 0; idx < type_list.GetSize(); idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - retval.Append(SBType(type_sp)); - } + for (const TypeSP &type_sp : results.GetTypeMap().Types()) + retval.Append(SBType(type_sp)); } } return retval; diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 2d02955..8e616af 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -1804,21 +1804,13 @@ lldb::SBType SBTarget::FindFirstType(const char *typename_cstr) { TargetSP target_sp(GetSP()); if (typename_cstr && typename_cstr[0] && target_sp) { ConstString const_typename(typename_cstr); - SymbolContext sc; - const bool exact_match = false; - - const ModuleList &module_list = target_sp->GetImages(); - size_t count = module_list.GetSize(); - for (size_t idx = 0; idx < count; idx++) { - ModuleSP module_sp(module_list.GetModuleAtIndex(idx)); - if (module_sp) { - TypeSP type_sp( - module_sp->FindFirstType(sc, const_typename, exact_match)); - if (type_sp) - return SBType(type_sp); - } - } - + TypeQuery query(const_typename.GetStringRef(), + TypeQueryOptions::e_find_one); + TypeResults results; + target_sp->GetImages().FindTypes(/*search_first=*/nullptr, query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return SBType(type_sp); // Didn't find the type in the symbols; Try the loaded language runtimes. if (auto process_sp = target_sp->GetProcessSP()) { for (auto *runtime : process_sp->GetLanguageRuntimes()) { @@ -1859,17 +1851,11 @@ lldb::SBTypeList SBTarget::FindTypes(const char *typename_cstr) { if (typename_cstr && typename_cstr[0] && target_sp) { ModuleList &images = target_sp->GetImages(); ConstString const_typename(typename_cstr); - bool exact_match = false; - TypeList type_list; - llvm::DenseSet<SymbolFile *> searched_symbol_files; - images.FindTypes(nullptr, const_typename, exact_match, UINT32_MAX, - searched_symbol_files, type_list); - - for (size_t idx = 0; idx < type_list.GetSize(); idx++) { - TypeSP type_sp(type_list.GetTypeAtIndex(idx)); - if (type_sp) - sb_type_list.Append(SBType(type_sp)); - } + TypeQuery query(typename_cstr); + TypeResults results; + images.FindTypes(nullptr, query, results); + for (const TypeSP &type_sp : results.GetTypeMap().Types()) + sb_type_list.Append(SBType(type_sp)); // Try the loaded language runtimes if (auto process_sp = target_sp->GetProcessSP()) { diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index b02b7de..4ecac73 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -372,8 +372,6 @@ protected: if (view_as_type_cstr && view_as_type_cstr[0]) { // We are viewing memory as a type - const bool exact_match = false; - TypeList type_list; uint32_t reference_count = 0; uint32_t pointer_count = 0; size_t idx; @@ -452,18 +450,18 @@ protected: } } - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; ConstString lookup_type_name(type_str.c_str()); StackFrame *frame = m_exe_ctx.GetFramePtr(); ModuleSP search_first; - if (frame) { + if (frame) search_first = frame->GetSymbolContext(eSymbolContextModule).module_sp; - } - target->GetImages().FindTypes(search_first.get(), lookup_type_name, - exact_match, 1, searched_symbol_files, - type_list); + TypeQuery query(lookup_type_name.GetStringRef(), + TypeQueryOptions::e_find_one); + TypeResults results; + target->GetImages().FindTypes(search_first.get(), query, results); + TypeSP type_sp = results.GetFirstType(); - if (type_list.GetSize() == 0 && lookup_type_name.GetCString()) { + if (!type_sp && lookup_type_name.GetCString()) { LanguageType language_for_type = m_memory_options.m_language_for_type.GetCurrentValue(); std::set<LanguageType> languages_to_check; @@ -499,15 +497,14 @@ protected: } if (!compiler_type.IsValid()) { - if (type_list.GetSize() == 0) { + if (type_sp) { + compiler_type = type_sp->GetFullCompilerType(); + } else { result.AppendErrorWithFormat("unable to find any types that match " "the raw type '%s' for full type '%s'\n", lookup_type_name.GetCString(), view_as_type_cstr); return; - } else { - TypeSP type_sp(type_list.GetTypeAtIndex(0)); - compiler_type = type_sp->GetFullCompilerType(); } } diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 63232c2..bc8bc51 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -1706,16 +1706,18 @@ static size_t LookupTypeInModule(Target *target, CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name_cstr, bool name_is_regex) { - TypeList type_list; if (module && name_cstr && name_cstr[0]) { - const uint32_t max_num_matches = UINT32_MAX; - bool name_is_fully_qualified = false; - - ConstString name(name_cstr); - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - module->FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); + TypeQuery query(name_cstr); + TypeResults results; + module->FindTypes(query, results); + TypeList type_list; + SymbolContext sc; + if (module) + sc.module_sp = module->shared_from_this(); + // Sort the type results and put the results that matched in \a module + // first if \a module was specified. + sc.SortTypeList(results.GetTypeMap(), type_list); if (type_list.Empty()) return 0; @@ -1748,22 +1750,21 @@ static size_t LookupTypeInModule(Target *target, } strm.EOL(); } + return type_list.GetSize(); } - return type_list.GetSize(); + return 0; } static size_t LookupTypeHere(Target *target, CommandInterpreter &interpreter, Stream &strm, Module &module, const char *name_cstr, bool name_is_regex) { + TypeQuery query(name_cstr); + TypeResults results; + module.FindTypes(query, results); TypeList type_list; - const uint32_t max_num_matches = UINT32_MAX; - bool name_is_fully_qualified = false; - - ConstString name(name_cstr); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module.FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); - + SymbolContext sc; + sc.module_sp = module.shared_from_this(); + sc.SortTypeList(results.GetTypeMap(), type_list); if (type_list.Empty()) return 0; @@ -2082,7 +2083,7 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all symtabs with {0} " "of {1} dumped.", num_dumped, num_modules)) break; @@ -2112,8 +2113,8 @@ protected: result.GetOutputStream().EOL(); result.GetOutputStream().EOL(); } - if (INTERRUPT_REQUESTED(GetDebugger(), - "Interrupted in dump symtab list with {0} of {1} dumped.", + if (INTERRUPT_REQUESTED(GetDebugger(), + "Interrupted in dump symtab list with {0} of {1} dumped.", num_dumped, num_matches)) break; @@ -2175,7 +2176,7 @@ protected: result.GetOutputStream().Format("Dumping sections for {0} modules.\n", num_modules); for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all sections with {0} of {1} dumped", image_idx, num_modules)) break; @@ -2196,7 +2197,7 @@ protected: FindModulesByName(target, arg_cstr, module_list, true); if (num_matches > 0) { for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump section list with {0} of {1} dumped.", i, num_matches)) break; @@ -2338,7 +2339,7 @@ protected: } for (size_t i = 0; i < num_matches; ++i) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump clang ast list with {0} of {1} dumped.", i, num_matches)) break; @@ -2477,9 +2478,9 @@ protected: if (num_modules > 0) { uint32_t num_dumped = 0; for (ModuleSP module_sp : target_modules.ModulesNoLocking()) { - if (INTERRUPT_REQUESTED(GetDebugger(), + if (INTERRUPT_REQUESTED(GetDebugger(), "Interrupted in dump all line tables with " - "{0} of {1} dumped", num_dumped, + "{0} of {1} dumped", num_dumped, num_modules)) break; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index e6279a0..65a65c4 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -949,99 +949,9 @@ void Module::FindAddressesForLine(const lldb::TargetSP target_sp, } } -void Module::FindTypes_Impl( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { +void Module::FindTypes(const TypeQuery &query, TypeResults &results) { if (SymbolFile *symbols = GetSymbolFile()) - symbols->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); -} - -void Module::FindTypesInNamespace(ConstString type_name, - const CompilerDeclContext &parent_decl_ctx, - size_t max_matches, TypeList &type_list) { - TypeMap types_map; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - FindTypes_Impl(type_name, parent_decl_ctx, max_matches, searched_symbol_files, - types_map); - if (types_map.GetSize()) { - SymbolContext sc; - sc.module_sp = shared_from_this(); - sc.SortTypeList(types_map, type_list); - } -} - -lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, ConstString name, - bool exact_match) { - TypeList type_list; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - FindTypes(name, exact_match, 1, searched_symbol_files, type_list); - if (type_list.GetSize()) - return type_list.GetTypeAtIndex(0); - return TypeSP(); -} - -void Module::FindTypes( - ConstString name, bool exact_match, size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeList &types) { - const char *type_name_cstr = name.GetCString(); - llvm::StringRef type_scope; - llvm::StringRef type_basename; - TypeClass type_class = eTypeClassAny; - TypeMap typesmap; - - if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename, - type_class)) { - // Check if "name" starts with "::" which means the qualified type starts - // from the root namespace and implies and exact match. The typenames we - // get back from clang do not start with "::" so we need to strip this off - // in order to get the qualified names to match - exact_match = type_scope.consume_front("::"); - - ConstString type_basename_const_str(type_basename); - FindTypes_Impl(type_basename_const_str, CompilerDeclContext(), max_matches, - searched_symbol_files, typesmap); - if (typesmap.GetSize()) - typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, - exact_match); - } else { - // The type is not in a namespace/class scope, just search for it by - // basename - if (type_class != eTypeClassAny && !type_basename.empty()) { - // The "type_name_cstr" will have been modified if we have a valid type - // class prefix (like "struct", "class", "union", "typedef" etc). - FindTypes_Impl(ConstString(type_basename), CompilerDeclContext(), - UINT_MAX, searched_symbol_files, typesmap); - typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, - exact_match); - } else { - FindTypes_Impl(name, CompilerDeclContext(), UINT_MAX, - searched_symbol_files, typesmap); - if (exact_match) { - typesmap.RemoveMismatchedTypes(type_scope, name, type_class, - exact_match); - } - } - } - if (typesmap.GetSize()) { - SymbolContext sc; - sc.module_sp = shared_from_this(); - sc.SortTypeList(typesmap, types); - } -} - -void Module::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - // If a scoped timer is needed, place it in a SymbolFile::FindTypes override. - // A timer here is too high volume for some cases, for example when calling - // FindTypes on each object file. - if (SymbolFile *symbols = GetSymbolFile()) - symbols->FindTypes(pattern, languages, searched_symbol_files, types); + symbols->FindTypes(query, results); } static Debugger::DebuggerList diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 04a9df7d..aa89c93 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -557,36 +557,21 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } -void ModuleList::FindTypes(Module *search_first, ConstString name, - bool name_is_fully_qualified, size_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeList &types) const { +void ModuleList::FindTypes(Module *search_first, const TypeQuery &query, + TypeResults &results) const { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - - collection::const_iterator pos, end = m_modules.end(); if (search_first) { - for (pos = m_modules.begin(); pos != end; ++pos) { - if (search_first == pos->get()) { - search_first->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); - - if (types.GetSize() >= max_matches) - return; - } - } - } - - for (pos = m_modules.begin(); pos != end; ++pos) { - // Search the module if the module is not equal to the one in the symbol - // context "sc". If "sc" contains a empty module shared pointer, then the - // comparison will always be true (valid_module_ptr != nullptr). - if (search_first != pos->get()) - (*pos)->FindTypes(name, name_is_fully_qualified, max_matches, - searched_symbol_files, types); - - if (types.GetSize() >= max_matches) + search_first->FindTypes(query, results); + if (results.Done(query)) return; } + for (const auto &module_sp : m_modules) { + if (search_first != module_sp.get()) { + module_sp->FindTypes(query, results); + if (results.Done(query)) + return; + } + } } bool ModuleList::FindSourceFile(const FileSpec &orig_spec, diff --git a/lldb/source/DataFormatters/TypeFormat.cpp b/lldb/source/DataFormatters/TypeFormat.cpp index 126240a..409c452 100644 --- a/lldb/source/DataFormatters/TypeFormat.cpp +++ b/lldb/source/DataFormatters/TypeFormat.cpp @@ -161,13 +161,12 @@ bool TypeFormatImpl_EnumType::FormatObject(ValueObject *valobj, if (!target_sp) return false; const ModuleList &images(target_sp->GetImages()); - TypeList types; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - images.FindTypes(nullptr, m_enum_type, false, UINT32_MAX, - searched_symbol_files, types); - if (types.Empty()) + TypeQuery query(m_enum_type.GetStringRef()); + TypeResults results; + images.FindTypes(nullptr, query, results); + if (results.GetTypeMap().Empty()) return false; - for (lldb::TypeSP type_sp : types.Types()) { + for (lldb::TypeSP type_sp : results.GetTypeMap().Types()) { if (!type_sp) continue; if ((type_sp->GetForwardCompilerType().GetTypeInfo() & diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 5d7e125..00ab6a0 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -201,19 +201,17 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { LLDB_LOG(log, " CTD Searching namespace {0} in module {1}", item.second.GetName(), item.first->GetFileSpec().GetFilename()); - TypeList types; - ConstString name(decl->getName()); - item.first->FindTypesInNamespace(name, item.second, UINT32_MAX, types); - - for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; + // Create a type matcher using the CompilerDeclContext for the namespace + // as the context (item.second) and search for the name inside of this + // context. + TypeQuery query(item.second, name); + TypeResults results; + item.first->FindTypes(query, results); - CompilerType clang_type(type->GetFullCompilerType()); + for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) { + CompilerType clang_type(type_sp->GetFullCompilerType()); if (!ClangUtil::IsClangType(clang_type)) continue; @@ -233,24 +231,15 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { } } } else { - TypeList types; - - ConstString name(decl->getName()); - const ModuleList &module_list = m_target->GetImages(); + // Create a type matcher using a CompilerDecl. Each TypeSystem class knows + // how to fill out a CompilerContext array using a CompilerDecl. + TypeQuery query(CompilerDecl(m_clang_ast_context, (void *)decl)); + TypeResults results; + module_list.FindTypes(nullptr, query, results); + for (const lldb::TypeSP &type_sp : results.GetTypeMap().Types()) { - bool exact_match = false; - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_list.FindTypes(nullptr, name, exact_match, UINT32_MAX, - searched_symbol_files, types); - - for (uint32_t ti = 0, te = types.GetSize(); ti != te; ++ti) { - lldb::TypeSP type = types.GetTypeAtIndex(ti); - - if (!type) - continue; - - CompilerType clang_type(type->GetFullCompilerType()); + CompilerType clang_type(type_sp->GetFullCompilerType()); if (!ClangUtil::IsClangType(clang_type)) continue; @@ -263,13 +252,6 @@ TagDecl *ClangASTSource::FindCompleteType(const TagDecl *decl) { TagDecl *candidate_tag_decl = const_cast<TagDecl *>(tag_type->getDecl()); - // We have found a type by basename and we need to make sure the decl - // contexts are the same before we can try to complete this type with - // another - if (!TypeSystemClang::DeclsAreEquivalent(const_cast<TagDecl *>(decl), - candidate_tag_decl)) - continue; - if (TypeSystemClang::GetCompleteDecl(&candidate_tag_decl->getASTContext(), candidate_tag_decl)) return candidate_tag_decl; @@ -614,41 +596,40 @@ void ClangASTSource::FindExternalVisibleDecls( if (context.m_found_type) return; - TypeList types; - const bool exact_match = true; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - if (module_sp && namespace_decl) - module_sp->FindTypesInNamespace(name, namespace_decl, 1, types); - else { - m_target->GetImages().FindTypes(module_sp.get(), name, exact_match, 1, - searched_symbol_files, types); + lldb::TypeSP type_sp; + TypeResults results; + if (module_sp && namespace_decl) { + // Match the name in the specified decl context. + TypeQuery query(namespace_decl, name, TypeQueryOptions::e_find_one); + module_sp->FindTypes(query, results); + type_sp = results.GetFirstType(); + } else { + // Match the exact name of the type at the root level. + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match | + TypeQueryOptions::e_find_one); + m_target->GetImages().FindTypes(nullptr, query, results); + type_sp = results.GetFirstType(); } - if (size_t num_types = types.GetSize()) { - for (size_t ti = 0; ti < num_types; ++ti) { - lldb::TypeSP type_sp = types.GetTypeAtIndex(ti); - - if (log) { - const char *name_string = type_sp->GetName().GetCString(); - - LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name, - (name_string ? name_string : "<anonymous>")); - } + if (type_sp) { + if (log) { + const char *name_string = type_sp->GetName().GetCString(); - CompilerType full_type = type_sp->GetFullCompilerType(); + LLDB_LOG(log, " CAS::FEVD Matching type found for \"{0}\": {1}", name, + (name_string ? name_string : "<anonymous>")); + } - CompilerType copied_clang_type(GuardedCopyType(full_type)); + CompilerType full_type = type_sp->GetFullCompilerType(); - if (!copied_clang_type) { - LLDB_LOG(log, " CAS::FEVD - Couldn't export a type"); + CompilerType copied_clang_type(GuardedCopyType(full_type)); - continue; - } + if (!copied_clang_type) { + LLDB_LOG(log, " CAS::FEVD - Couldn't export a type"); + } else { context.AddTypeDecl(copied_clang_type); context.m_found_type = true; - break; } } diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index a5c9ead..0ea9201 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -82,24 +82,30 @@ TypeAndOrName ItaniumABILanguageRuntime::GetTypeInfo( lookup_name.append(class_name.data(), class_name.size()); type_info.SetName(class_name); - const bool exact_match = true; + ConstString const_lookup_name(lookup_name); TypeList class_types; - + ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule(); // First look in the module that the vtable symbol came from and // look for a single exact match. - llvm::DenseSet<SymbolFile *> searched_symbol_files; - ModuleSP module_sp = vtable_info.symbol->CalculateSymbolContextModule(); - if (module_sp) - module_sp->FindTypes(ConstString(lookup_name), exact_match, 1, - searched_symbol_files, class_types); + TypeResults results; + TypeQuery query(const_lookup_name.GetStringRef(), + TypeQueryOptions::e_exact_match | + TypeQueryOptions::e_find_one); + if (module_sp) { + module_sp->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + class_types.Insert(type_sp); + } // If we didn't find a symbol, then move on to the entire module // list in the target and get as many unique matches as possible - Target &target = m_process->GetTarget(); - if (class_types.Empty()) - target.GetImages().FindTypes(nullptr, ConstString(lookup_name), - exact_match, UINT32_MAX, - searched_symbol_files, class_types); + if (class_types.Empty()) { + query.SetFindOne(false); + m_process->GetTarget().GetImages().FindTypes(nullptr, query, results); + for (const auto &type_sp : results.GetTypeMap().Types()) + class_types.Insert(type_sp); + } lldb::TypeSP type_sp; if (class_types.Empty()) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp index 289288a..ba52444 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.cpp @@ -139,17 +139,10 @@ ObjCLanguageRuntime::LookupInCompleteClassCache(ConstString &name) { if (!module_sp) return TypeSP(); - const bool exact_match = true; - const uint32_t max_matches = UINT32_MAX; - TypeList types; - - llvm::DenseSet<SymbolFile *> searched_symbol_files; - module_sp->FindTypes(name, exact_match, max_matches, searched_symbol_files, - types); - - for (uint32_t i = 0; i < types.GetSize(); ++i) { - TypeSP type_sp(types.GetTypeAtIndex(i)); - + TypeQuery query(name.GetStringRef(), TypeQueryOptions::e_exact_match); + TypeResults results; + module_sp->FindTypes(query, results); + for (const TypeSP &type_sp : results.GetTypeMap().Types()) { if (TypeSystemClang::IsObjCObjectOrInterfaceType( type_sp->GetForwardCompilerType())) { if (TypePayloadClang(type_sp->GetPayload()).IsCompleteObjCClass()) { diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp index cd52233..729d6af 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp @@ -448,15 +448,6 @@ void SymbolFileBreakpad::FindFunctions(const RegularExpression ®ex, // TODO } -void SymbolFileBreakpad::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - -void SymbolFileBreakpad::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {} - void SymbolFileBreakpad::AddSymbols(Symtab &symtab) { Log *log = GetLog(LLDBLog::Symbols); Module &module = *m_objfile_sp->GetModule(); diff --git a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h index 4a01a64..214fbdd 100644 --- a/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h +++ b/lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h @@ -118,15 +118,6 @@ public: void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override { return llvm::make_error<llvm::StringError>( diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp index 7a2b4c0..d192944 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.cpp @@ -1020,23 +1020,18 @@ lldb_private::Type *SymbolFileCTF::ResolveTypeUID(lldb::user_id_t type_uid) { return type_sp.get(); } -void SymbolFileCTF::FindTypes( - lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) { - - searched_symbol_files.clear(); - searched_symbol_files.insert(this); +void SymbolFileCTF::FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) { + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) + return; - size_t matches = 0; + ConstString name = match.GetTypeBasename(); for (TypeSP type_sp : GetTypeList().Types()) { - if (matches == max_matches) - break; if (type_sp && type_sp->GetName() == name) { - types.Insert(type_sp); - matches++; + results.InsertUnique(type_sp); + if (results.Done(match)) + return; } } } diff --git a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h index 787dc18..f111937 100644 --- a/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h +++ b/lldb/source/Plugins/SymbolFile/CTF/SymbolFileCTF.h @@ -105,12 +105,8 @@ public: lldb::TypeClass type_mask, lldb_private::TypeList &type_list) override {} - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index e3c6464..3348766 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -152,16 +152,16 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, // If this type comes from a Clang module, recursively look in the // DWARF section of the .pcm file in the module cache. Clang // generates DWO skeleton units as breadcrumbs to find them. - std::vector<CompilerContext> decl_context = die.GetDeclContext(); - TypeMap pcm_types; + std::vector<lldb_private::CompilerContext> die_context = die.GetDeclContext(); + TypeQuery query(die_context, TypeQueryOptions::e_module_search | + TypeQueryOptions::e_find_one); + TypeResults results; // The type in the Clang module must have the same language as the current CU. - LanguageSet languages; - languages.Insert(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - clang_module_sp->GetSymbolFile()->FindTypes(decl_context, languages, - searched_symbol_files, pcm_types); - if (pcm_types.Empty()) { + query.AddLanguage(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())); + clang_module_sp->FindTypes(query, results); + TypeSP pcm_type_sp = results.GetTypeMap().FirstType(); + if (!pcm_type_sp) { // Since this type is defined in one of the Clang modules imported // by this symbol file, search all of them. Instead of calling // sym_file->FindTypes(), which would return this again, go straight @@ -170,24 +170,20 @@ TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, // Well-formed clang modules never form cycles; guard against corrupted // ones by inserting the current file. - searched_symbol_files.insert(&sym_file); + results.AlreadySearched(&sym_file); sym_file.ForEachExternalModule( - *sc.comp_unit, searched_symbol_files, [&](Module &module) { - module.GetSymbolFile()->FindTypes(decl_context, languages, - searched_symbol_files, pcm_types); - return pcm_types.GetSize(); + *sc.comp_unit, results.GetSearchedSymbolFiles(), [&](Module &module) { + module.FindTypes(query, results); + pcm_type_sp = results.GetTypeMap().FirstType(); + return !pcm_type_sp; }); } - if (!pcm_types.GetSize()) + if (!pcm_type_sp) return TypeSP(); // We found a real definition for this type in the Clang module, so lets use // it and cache the fact that we found a complete type for this die. - TypeSP pcm_type_sp = pcm_types.GetTypeAtIndex(0); - if (!pcm_type_sp) - return TypeSP(); - lldb_private::CompilerType pcm_type = pcm_type_sp->GetForwardCompilerType(); lldb_private::CompilerType type = GetClangASTImporter().CopyType(m_ast, pcm_type); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp index 1f9524f..bed68f4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp @@ -418,6 +418,54 @@ std::vector<lldb_private::CompilerContext> DWARFDIE::GetDeclContext() const { return context; } +std::vector<lldb_private::CompilerContext> +DWARFDIE::GetTypeLookupContext() const { + std::vector<lldb_private::CompilerContext> context; + // If there is no name, then there is no need to look anything up for this + // DIE. + const char *name = GetName(); + if (!name || !name[0]) + return context; + const dw_tag_t tag = Tag(); + if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) + return context; + DWARFDIE parent = GetParent(); + if (parent) + context = parent.GetTypeLookupContext(); + auto push_ctx = [&](CompilerContextKind kind, llvm::StringRef name) { + context.push_back({kind, ConstString(name)}); + }; + switch (tag) { + case DW_TAG_namespace: + push_ctx(CompilerContextKind::Namespace, name); + break; + case DW_TAG_structure_type: + push_ctx(CompilerContextKind::Struct, name); + break; + case DW_TAG_union_type: + push_ctx(CompilerContextKind::Union, name); + break; + case DW_TAG_class_type: + push_ctx(CompilerContextKind::Class, name); + break; + case DW_TAG_enumeration_type: + push_ctx(CompilerContextKind::Enum, name); + break; + case DW_TAG_variable: + push_ctx(CompilerContextKind::Variable, GetPubname()); + break; + case DW_TAG_typedef: + push_ctx(CompilerContextKind::Typedef, name); + break; + case DW_TAG_base_type: + push_ctx(CompilerContextKind::Builtin, name); + break; + default: + break; + } + return context; +} + DWARFDIE DWARFDIE::GetParentDeclContextDIE() const { if (IsValid()) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h index a68af62c..511ca62 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h @@ -73,9 +73,22 @@ public: std::vector<DWARFDIE> GetDeclContextDIEs() const; /// Return this DIE's decl context as it is needed to look up types - /// in Clang's -gmodules debug info format. + /// in Clang modules. This context will include any modules or functions that + /// the type is declared in so an exact module match can be efficiently made. std::vector<CompilerContext> GetDeclContext() const; + /// Get a context to a type so it can be looked up. + /// + /// This function uses the current DIE to fill in a CompilerContext array + /// that is suitable for type lookup for comparison to a TypeQuery's compiler + /// context (TypeQuery::GetContextRef()). If this DIE represents a named type, + /// it should fill out the compiler context with the type itself as the last + /// entry. The declaration context should be above the type and stop at an + /// appropriate time, like either the translation unit or at a function + /// context. This is designed to allow users to efficiently look for types + /// using a full or partial CompilerContext array. + std::vector<CompilerContext> GetTypeLookupContext() const; + // Getting attribute values from the DIE. // // GetAttributeValueAsXXX() functions should only be used if you are diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index d4c573e..7eddc50 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2596,177 +2596,157 @@ void SymbolFileDWARF::GetMangledNamesForFunction( } } -void SymbolFileDWARF::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - Log *log = GetLog(DWARFLog::Lookups); +/// Split a name up into a basename and template parameters. +static bool SplitTemplateParams(llvm::StringRef fullname, + llvm::StringRef &basename, + llvm::StringRef &template_params) { + auto it = fullname.find('<'); + if (it == llvm::StringRef::npos) { + basename = fullname; + template_params = llvm::StringRef(); + return false; + } + basename = fullname.slice(0, it); + template_params = fullname.slice(it, fullname.size()); + return true; +} - if (log) { - if (parent_decl_ctx) - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "{1:p} (\"{2}\"), max_matches={3}, type_list)", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches); - else - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx = " - "NULL, max_matches={1}, type_list)", - name.GetCString(), max_matches); +static bool UpdateCompilerContextForSimpleTemplateNames(TypeQuery &match) { + // We need to find any names in the context that have template parameters + // and strip them so the context can be matched when -gsimple-template-names + // is being used. Returns true if any of the context items were updated. + bool any_context_updated = false; + for (auto &context : match.GetContextRef()) { + llvm::StringRef basename, params; + if (SplitTemplateParams(context.name.GetStringRef(), basename, params)) { + context.name = ConstString(basename); + any_context_updated = true; + } } + return any_context_updated; +} +void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) return; - // Unlike FindFunctions(), FindTypes() following cannot produce false - // positives. - - const llvm::StringRef name_ref = name.GetStringRef(); - auto name_bracket_index = name_ref.find('<'); - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + bool have_index_match = false; + m_index->GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // With -gsimple-template-names, a templated type's DW_AT_name will not - // contain the template parameters. Make sure that if the original query - // didn't contain a '<', we filter out entries with template parameters. - if (name_bracket_index == llvm::StringRef::npos && - matching_type->IsTemplateType()) - return true; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. - // We found a type pointer, now find the shared pointer form our type - // list - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + if (matching_type->IsTemplateType()) { + // We have to watch out for case where we lookup a type by basename and + // it matches a template with simple template names. Like looking up + // "Foo" and if we have simple template names then we will match + // "Foo<int>" and "Foo<double>" because all the DWARF has is "Foo" in + // the accelerator tables. The main case we see this in is when the + // expression parser is trying to parse "Foo<int>" and it will first do + // a lookup on just "Foo". We verify the type basename matches before + // inserting the type in the results. + auto CompilerTypeBasename = + matching_type->GetForwardCompilerType().GetTypeName(true); + if (CompilerTypeBasename != query.GetTypeBasename()) + return true; // Keep iterating over index types, basename mismatch. + } + have_index_match = true; + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; + // With -gsimple-template-names, a templated type's DW_AT_name will not // contain the template parameters. Try again stripping '<' and anything // after, filtering out entries with template parameters that don't match. - if (types.GetSize() < max_matches) { - if (name_bracket_index != llvm::StringRef::npos) { - const llvm::StringRef name_no_template_params = - name_ref.slice(0, name_bracket_index); - const llvm::StringRef template_params = - name_ref.slice(name_bracket_index, name_ref.size()); - m_index->GetTypes(ConstString(name_no_template_params), [&](DWARFDIE die) { - if (!DIEInDeclContext(parent_decl_ctx, die)) - return true; // The containing decl contexts don't match - - const llvm::StringRef base_name = GetTypeForDIE(die)->GetBaseName().AsCString(); - auto it = base_name.find('<'); - // If the candidate qualified name doesn't have '<', it doesn't have - // template params to compare. - if (it == llvm::StringRef::npos) - return true; - - // Filter out non-matching instantiations by comparing template params. - const llvm::StringRef base_name_template_params = - base_name.slice(it, base_name.size()); - - if (template_params != base_name_template_params) - return true; - - Type *matching_type = ResolveType(die, true, true); - if (!matching_type) - return true; + if (!have_index_match) { + // Create a type matcher with a compiler context that is tuned for + // -gsimple-template-names. We will use this for the index lookup and the + // context matching, but will use the original "match" to insert matches + // into if things match. The "match_simple" has a compiler context with + // all template parameters removed to allow the names and context to match. + // The UpdateCompilerContextForSimpleTemplateNames(...) will return true if + // it trims any context items down by removing template parameter names. + TypeQuery query_simple(query); + if (UpdateCompilerContextForSimpleTemplateNames(query_simple)) { + + // Copy our match's context and update the basename we are looking for + // so we can use this only to compare the context correctly. + m_index->GetTypes(query_simple.GetTypeBasename(), [&](DWARFDIE die) { + // Check the language, but only if we have a language filter. + if (query.HasLanguage()) { + if (!query.LanguageMatches(GetLanguageFamily(*die.GetCU()))) + return true; // Keep iterating over index types, language mismatch. + } - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - return types.GetSize() < max_matches; + // Check the context matches + std::vector<lldb_private::CompilerContext> die_context; + if (query.GetModuleSearch()) + die_context = die.GetDeclContext(); + else + die_context = die.GetTypeLookupContext(); + assert(!die_context.empty()); + if (!query_simple.ContextMatches(die_context)) + return true; // Keep iterating over index types, context mismatch. + + // Try to resolve the type. + if (Type *matching_type = ResolveType(die, true, true)) { + ConstString name = matching_type->GetQualifiedName(); + // We have found a type that still might not match due to template + // parameters. If we create a new TypeQuery that uses the new type's + // fully qualified name, we can find out if this type matches at all + // context levels. We can't use just the "match_simple" context + // because all template parameters were stripped off. The fully + // qualified name of the type will have the template parameters and + // will allow us to make sure it matches correctly. + TypeQuery die_query(name.GetStringRef(), + TypeQueryOptions::e_exact_match); + if (!query.ContextMatches(die_query.GetContextRef())) + return true; // Keep iterating over index types, context mismatch. + + results.InsertUnique(matching_type->shared_from_this()); + } + return !results.Done(query); // Keep iterating if we aren't done. }); + if (results.Done(query)) + return; } } // Next search through the reachable Clang modules. This only applies for // DWARF objects compiled with -gmodules that haven't been processed by // dsymutil. - if (types.GetSize() < max_matches) { - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - if (SymbolFile *sym_file = external_module_sp->GetSymbolFile()) - sym_file->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); - } + UpdateExternalModuleListIfNeeded(); - if (log && types.GetSize()) { - if (parent_decl_ctx) { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= {1:p} (\"{2}\"), max_matches={3}, type_list) => {4}", - name.GetCString(), static_cast<const void *>(&parent_decl_ctx), - parent_decl_ctx.GetName().AsCString("<NULL>"), max_matches, - types.GetSize()); - } else { - GetObjectFile()->GetModule()->LogMessage( - log, - "SymbolFileDWARF::FindTypes (sc, name=\"{0}\", parent_decl_ctx " - "= NULL, max_matches={1}, type_list) => {2}", - name.GetCString(), max_matches, types.GetSize()); + for (const auto &pair : m_external_type_modules) { + if (ModuleSP external_module_sp = pair.second) { + external_module_sp->FindTypes(query, results); + if (results.Done(query)) + return; } } } -void SymbolFileDWARF::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { - // Make sure we haven't already searched this SymbolFile before. - if (!searched_symbol_files.insert(this).second) - return; - - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (pattern.empty()) - return; - - ConstString name = pattern.back().name; - - if (!name) - return; - - m_index->GetTypes(name, [&](DWARFDIE die) { - if (!languages[GetLanguageFamily(*die.GetCU())]) - return true; - - std::vector<CompilerContext> die_context = die.GetDeclContext(); - if (!contextMatches(die_context, pattern)) - return true; - - if (Type *matching_type = ResolveType(die, true, true)) { - // We found a type pointer, now find the shared pointer form our type - // list. - types.InsertUnique(matching_type->shared_from_this()); - } - return true; - }); - - // Next search through the reachable Clang modules. This only applies for - // DWARF objects compiled with -gmodules that haven't been processed by - // dsymutil. - UpdateExternalModuleListIfNeeded(); - - for (const auto &pair : m_external_type_modules) - if (ModuleSP external_module_sp = pair.second) - external_module_sp->FindTypes(pattern, languages, searched_symbol_files, - types); -} - CompilerDeclContext SymbolFileDWARF::FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index e6efbba..78819ed 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -186,14 +186,8 @@ public: GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names) override; - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; void GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask, TypeList &type_list) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 263ada9..e5b59460 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1227,27 +1227,12 @@ TypeSP SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE( return TypeSP(); } -void SymbolFileDWARFDebugMap::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { +void SymbolFileDWARFDebugMap::FindTypes(const TypeQuery &query, + TypeResults &results) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); - return types.GetSize() >= max_matches; - }); -} - -void SymbolFileDWARFDebugMap::FindTypes( - llvm::ArrayRef<CompilerContext> context, LanguageSet languages, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - LLDB_SCOPED_TIMER(); - ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool { - oso_dwarf->FindTypes(context, languages, searched_symbol_files, types); - return false; + oso_dwarf->FindTypes(query, results); + return !results.Done(query); // Keep iterating if we aren't done. }); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 13f94f6..cd0a4bb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -118,13 +118,8 @@ public: bool include_inlines, SymbolContextList &sc_list) override; void FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) override; - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - void FindTypes(llvm::ArrayRef<CompilerContext> context, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; CompilerDeclContext FindNamespace(ConstString name, const CompilerDeclContext &parent_decl_ctx, bool only_root_namespaces) override; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index eaca476..35c2575 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1717,24 +1717,33 @@ void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, bool include_inlines, SymbolContextList &sc_list) {} -void SymbolFileNativePDB::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (!name) +void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, + lldb_private::TypeResults &results) { + + // Make sure we haven't already searched this SymbolFile before. + if (results.AlreadySearched(this)) return; - searched_symbol_files.clear(); - searched_symbol_files.insert(this); + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - // There is an assumption 'name' is not a regex - FindTypesByName(name.GetStringRef(), max_matches, types); -} + std::vector<TypeIndex> matches = + m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef()); -void SymbolFileNativePDB::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {} + for (TypeIndex type_idx : matches) { + TypeSP type_sp = GetOrCreateType(type_idx); + if (!type_sp) + continue; + + // We resolved a type. Get the fully qualified name to ensure it matches. + ConstString name = type_sp->GetQualifiedName(); + TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); + if (query.ContextMatches(type_match.GetContextRef())) { + results.InsertUnique(type_sp); + if (results.Done(query)) + return; + } + } +} void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, uint32_t max_matches, diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index bf64cd33..9d0458c 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -140,14 +140,8 @@ public: std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id); - void FindTypes(ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) override; + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(lldb::LanguageType language) override; diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp index 78eabc3..96036de 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp @@ -1446,24 +1446,6 @@ void SymbolFilePDB::AddSymbols(lldb_private::Symtab &symtab) { symtab.Finalize(); } -void SymbolFilePDB::FindTypes( - lldb_private::ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) { - std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); - if (!name) - return; - if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) - return; - - searched_symbol_files.clear(); - searched_symbol_files.insert(this); - - // There is an assumption 'name' is not a regex - FindTypesByName(name.GetStringRef(), parent_decl_ctx, max_matches, types); -} - void SymbolFilePDB::DumpClangAST(Stream &s) { auto type_system_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); @@ -1536,25 +1518,27 @@ void SymbolFilePDB::FindTypesByRegex( } } -void SymbolFilePDB::FindTypesByName( - llvm::StringRef name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, lldb_private::TypeMap &types) { +void SymbolFilePDB::FindTypes(const lldb_private::TypeQuery &query, + lldb_private::TypeResults &type_results) { + + // Make sure we haven't already searched this SymbolFile before. + if (type_results.AlreadySearched(this)) + return; + + std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + std::unique_ptr<IPDBEnumSymbols> results; - if (name.empty()) + llvm::StringRef basename = query.GetTypeBasename().GetStringRef(); + if (basename.empty()) return; results = m_global_scope_up->findAllChildren(PDB_SymType::None); if (!results) return; - uint32_t matches = 0; - while (auto result = results->getNext()) { - if (max_matches > 0 && matches >= max_matches) - break; if (MSVCUndecoratedNameParser::DropScope( - result->getRawSymbol().getName()) != name) + result->getRawSymbol().getName()) != basename) continue; switch (result->getSymTag()) { @@ -1573,23 +1557,20 @@ void SymbolFilePDB::FindTypesByName( if (!ResolveTypeUID(result->getSymIndexId())) continue; - if (parent_decl_ctx.IsValid() && - GetDeclContextContainingUID(result->getSymIndexId()) != parent_decl_ctx) - continue; - auto iter = m_types.find(result->getSymIndexId()); if (iter == m_types.end()) continue; - types.Insert(iter->second); - ++matches; + // We resolved a type. Get the fully qualified name to ensure it matches. + ConstString name = iter->second->GetQualifiedName(); + TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); + if (query.ContextMatches(type_match.GetContextRef())) { + type_results.InsertUnique(iter->second); + if (type_results.Done(query)) + return; + } } } -void SymbolFilePDB::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) {} - void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, uint32_t type_mask, TypeCollection &type_collection) { diff --git a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h index 5b98c6e..01851f1 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h +++ b/lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.h @@ -134,19 +134,8 @@ public: std::vector<lldb_private::ConstString> &mangled_names) override; void AddSymbols(lldb_private::Symtab &symtab) override; - - void - FindTypes(lldb_private::ConstString name, - const lldb_private::CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - - void FindTypes(llvm::ArrayRef<lldb_private::CompilerContext> pattern, - lldb_private::LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - lldb_private::TypeMap &types) override; - + void FindTypes(const lldb_private::TypeQuery &match, + lldb_private::TypeResults &results) override; void FindTypesByRegex(const lldb_private::RegularExpression ®ex, uint32_t max_matches, lldb_private::TypeMap &types); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 7c28935..47024cd 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -2461,89 +2461,6 @@ void TypeSystemClang::DumpDeclHiearchy(clang::Decl *decl) { } } -bool TypeSystemClang::DeclsAreEquivalent(clang::Decl *lhs_decl, - clang::Decl *rhs_decl) { - if (lhs_decl && rhs_decl) { - // Make sure the decl kinds match first - const clang::Decl::Kind lhs_decl_kind = lhs_decl->getKind(); - const clang::Decl::Kind rhs_decl_kind = rhs_decl->getKind(); - - if (lhs_decl_kind == rhs_decl_kind) { - // Now check that the decl contexts kinds are all equivalent before we - // have to check any names of the decl contexts... - clang::DeclContext *lhs_decl_ctx = lhs_decl->getDeclContext(); - clang::DeclContext *rhs_decl_ctx = rhs_decl->getDeclContext(); - if (lhs_decl_ctx && rhs_decl_ctx) { - while (true) { - if (lhs_decl_ctx && rhs_decl_ctx) { - const clang::Decl::Kind lhs_decl_ctx_kind = - lhs_decl_ctx->getDeclKind(); - const clang::Decl::Kind rhs_decl_ctx_kind = - rhs_decl_ctx->getDeclKind(); - if (lhs_decl_ctx_kind == rhs_decl_ctx_kind) { - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - - if (lhs_decl_ctx == nullptr && rhs_decl_ctx == nullptr) - break; - } else - return false; - } else - return false; - } - - // Now make sure the name of the decls match - clang::NamedDecl *lhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(lhs_decl); - clang::NamedDecl *rhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(rhs_decl); - if (lhs_named_decl && rhs_named_decl) { - clang::DeclarationName lhs_decl_name = lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } else - return false; - } else - return false; - - // We know that the decl context kinds all match, so now we need to - // make sure the names match as well - lhs_decl_ctx = lhs_decl->getDeclContext(); - rhs_decl_ctx = rhs_decl->getDeclContext(); - while (true) { - switch (lhs_decl_ctx->getDeclKind()) { - case clang::Decl::TranslationUnit: - // We don't care about the translation unit names - return true; - default: { - clang::NamedDecl *lhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(lhs_decl_ctx); - clang::NamedDecl *rhs_named_decl = - llvm::dyn_cast<clang::NamedDecl>(rhs_decl_ctx); - if (lhs_named_decl && rhs_named_decl) { - clang::DeclarationName lhs_decl_name = - lhs_named_decl->getDeclName(); - clang::DeclarationName rhs_decl_name = - rhs_named_decl->getDeclName(); - if (lhs_decl_name.getNameKind() == rhs_decl_name.getNameKind()) { - if (lhs_decl_name.getAsString() != rhs_decl_name.getAsString()) - return false; - } else - return false; - } else - return false; - } break; - } - lhs_decl_ctx = lhs_decl_ctx->getParent(); - rhs_decl_ctx = rhs_decl_ctx->getParent(); - } - } - } - } - return false; -} bool TypeSystemClang::GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl) { if (!decl) @@ -9070,6 +8987,66 @@ size_t TypeSystemClang::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } +static CompilerContextKind GetCompilerKind(clang::Decl::Kind clang_kind, + clang::DeclContext const *decl_ctx) { + switch (clang_kind) { + case Decl::TranslationUnit: + return CompilerContextKind::TranslationUnit; + case Decl::Namespace: + return CompilerContextKind::Namespace; + case Decl::Var: + return CompilerContextKind::Variable; + case Decl::Enum: + return CompilerContextKind::Enum; + case Decl::Typedef: + return CompilerContextKind::Typedef; + default: + // Many other kinds have multiple values + if (decl_ctx) { + if (decl_ctx->isFunctionOrMethod()) + return CompilerContextKind::Function; + else if (decl_ctx->isRecord()) + return (CompilerContextKind)((uint16_t)CompilerContextKind::Class | + (uint16_t)CompilerContextKind::Struct | + (uint16_t)CompilerContextKind::Union); + } + break; + } + return CompilerContextKind::Any; +} + +static void +InsertCompilerContext(TypeSystemClang *ts, clang::DeclContext *decl_ctx, + std::vector<lldb_private::CompilerContext> &context) { + if (decl_ctx == nullptr) + return; + InsertCompilerContext(ts, decl_ctx->getParent(), context); + clang::Decl::Kind clang_kind = decl_ctx->getDeclKind(); + if (clang_kind == Decl::TranslationUnit) + return; // Stop at the translation unit. + const CompilerContextKind compiler_kind = + GetCompilerKind(clang_kind, decl_ctx); + ConstString decl_ctx_name = ts->DeclContextGetName(decl_ctx); + context.push_back({compiler_kind, decl_ctx_name}); +} + +std::vector<lldb_private::CompilerContext> +TypeSystemClang::DeclGetCompilerContext(void *opaque_decl) { + std::vector<lldb_private::CompilerContext> context; + ConstString decl_name = DeclGetName(opaque_decl); + if (decl_name) { + clang::Decl *decl = (clang::Decl *)opaque_decl; + // Add the entire decl context first + clang::DeclContext *decl_ctx = decl->getDeclContext(); + InsertCompilerContext(this, decl_ctx, context); + // Now add the decl information + auto compiler_kind = + GetCompilerKind(decl->getKind(), dyn_cast<DeclContext>(decl)); + context.push_back({compiler_kind, decl_name}); + } + return context; +} + CompilerType TypeSystemClang::DeclGetFunctionArgumentType(void *opaque_decl, size_t idx) { if (clang::FunctionDecl *func_decl = @@ -9308,6 +9285,14 @@ bool TypeSystemClang::DeclContextIsClassMethod(void *opaque_decl_ctx) { return false; } +std::vector<lldb_private::CompilerContext> +TypeSystemClang::DeclContextGetCompilerContext(void *opaque_decl_ctx) { + auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; + std::vector<lldb_private::CompilerContext> context; + InsertCompilerContext(this, decl_ctx, context); + return context; +} + bool TypeSystemClang::DeclContextIsContainedInLookup( void *opaque_decl_ctx, void *other_opaque_decl_ctx) { auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx; diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 19f2673..a731648 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -183,8 +183,6 @@ public: static void DumpDeclContextHiearchy(clang::DeclContext *decl_ctx); - static bool DeclsAreEquivalent(clang::Decl *lhs_decl, clang::Decl *rhs_decl); - static bool GetCompleteDecl(clang::ASTContext *ast, clang::Decl *decl); void SetMetadataAsUserID(const clang::Decl *decl, lldb::user_id_t user_id); @@ -558,6 +556,9 @@ public: CompilerType DeclGetFunctionArgumentType(void *opaque_decl, size_t arg_idx) override; + std::vector<lldb_private::CompilerContext> + DeclGetCompilerContext(void *opaque_decl) override; + CompilerType GetTypeForDecl(void *opaque_decl) override; // CompilerDeclContext override functions @@ -587,6 +588,9 @@ public: lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) override; + std::vector<lldb_private::CompilerContext> + DeclContextGetCompilerContext(void *opaque_decl_ctx) override; + // Clang specific clang::DeclContext functions static clang::DeclContext * diff --git a/lldb/source/Symbol/CompilerDecl.cpp b/lldb/source/Symbol/CompilerDecl.cpp index 3cafa95..0eb630e 100644 --- a/lldb/source/Symbol/CompilerDecl.cpp +++ b/lldb/source/Symbol/CompilerDecl.cpp @@ -47,3 +47,8 @@ bool lldb_private::operator!=(const lldb_private::CompilerDecl &lhs, return lhs.GetTypeSystem() != rhs.GetTypeSystem() || lhs.GetOpaqueDecl() != rhs.GetOpaqueDecl(); } + +std::vector<lldb_private::CompilerContext> +CompilerDecl::GetCompilerContext() const { + return m_type_system->DeclGetCompilerContext(m_opaque_decl); +} diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp index a188e60..b40a08e 100644 --- a/lldb/source/Symbol/CompilerDeclContext.cpp +++ b/lldb/source/Symbol/CompilerDeclContext.cpp @@ -59,6 +59,13 @@ bool CompilerDeclContext::IsContainedInLookup(CompilerDeclContext other) const { other.m_opaque_decl_ctx); } +std::vector<lldb_private::CompilerContext> +CompilerDeclContext::GetCompilerContext() const { + if (IsValid()) + return m_type_system->DeclContextGetCompilerContext(m_opaque_decl_ctx); + return {}; +} + bool lldb_private::operator==(const lldb_private::CompilerDeclContext &lhs, const lldb_private::CompilerDeclContext &rhs) { return lhs.GetTypeSystem() == rhs.GetTypeSystem() && diff --git a/lldb/source/Symbol/SymbolFile.cpp b/lldb/source/Symbol/SymbolFile.cpp index 4b9c386..e318e2be 100644 --- a/lldb/source/Symbol/SymbolFile.cpp +++ b/lldb/source/Symbol/SymbolFile.cpp @@ -134,17 +134,6 @@ void SymbolFile::GetMangledNamesForFunction( const std::string &scope_qualified_name, std::vector<ConstString> &mangled_names) {} -void SymbolFile::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - -void SymbolFile::FindTypes(llvm::ArrayRef<CompilerContext> pattern, - LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, - TypeMap &types) {} - void SymbolFile::AssertModuleLock() { // The code below is too expensive to leave enabled in release builds. It's // enabled in debug builds or when the correct macro is set. diff --git a/lldb/source/Symbol/SymbolFileOnDemand.cpp b/lldb/source/Symbol/SymbolFileOnDemand.cpp index 19b519c..3399525 100644 --- a/lldb/source/Symbol/SymbolFileOnDemand.cpp +++ b/lldb/source/Symbol/SymbolFileOnDemand.cpp @@ -431,31 +431,14 @@ void SymbolFileOnDemand::GetMangledNamesForFunction( mangled_names); } -void SymbolFileOnDemand::FindTypes( - ConstString name, const CompilerDeclContext &parent_decl_ctx, - uint32_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap &types) { - if (!m_debug_info_enabled) { - Log *log = GetLog(); - LLDB_LOG(log, "[{0}] {1}({2}) is skipped", GetSymbolFileName(), - __FUNCTION__, name); - return; - } - return m_sym_file_impl->FindTypes(name, parent_decl_ctx, max_matches, - searched_symbol_files, types); -} - -void SymbolFileOnDemand::FindTypes( - llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, - llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) { +void SymbolFileOnDemand::FindTypes(const TypeQuery &match, + TypeResults &results) { if (!m_debug_info_enabled) { LLDB_LOG(GetLog(), "[{0}] {1} is skipped", GetSymbolFileName(), __FUNCTION__); return; } - return m_sym_file_impl->FindTypes(pattern, languages, searched_symbol_files, - types); + return m_sym_file_impl->FindTypes(match, results); } void SymbolFileOnDemand::GetTypes(SymbolContextScope *sc_scope, diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp index 54eeace..293fe1b 100644 --- a/lldb/source/Symbol/Type.cpp +++ b/lldb/source/Symbol/Type.cpp @@ -64,6 +64,127 @@ bool lldb_private::contextMatches(llvm::ArrayRef<CompilerContext> context_chain, return true; } +static CompilerContextKind ConvertTypeClass(lldb::TypeClass type_class) { + if (type_class == eTypeClassAny) + return CompilerContextKind::AnyType; + uint16_t result = 0; + if (type_class & lldb::eTypeClassClass) + result |= (uint16_t)CompilerContextKind::Class; + if (type_class & lldb::eTypeClassStruct) + result |= (uint16_t)CompilerContextKind::Struct; + if (type_class & lldb::eTypeClassUnion) + result |= (uint16_t)CompilerContextKind::Union; + if (type_class & lldb::eTypeClassEnumeration) + result |= (uint16_t)CompilerContextKind::Enum; + if (type_class & lldb::eTypeClassFunction) + result |= (uint16_t)CompilerContextKind::Function; + if (type_class & lldb::eTypeClassTypedef) + result |= (uint16_t)CompilerContextKind::Typedef; + return (CompilerContextKind)result; +} + +TypeQuery::TypeQuery(llvm::StringRef name, TypeQueryOptions options) + : m_options(options) { + llvm::StringRef scope, basename; + lldb::TypeClass type_class = lldb::eTypeClassAny; + if (Type::GetTypeScopeAndBasename(name, scope, basename, type_class)) { + if (scope.consume_front("::")) + m_options |= e_exact_match; + if (!scope.empty()) { + std::pair<llvm::StringRef, llvm::StringRef> scope_pair = + scope.split("::"); + while (!scope_pair.second.empty()) { + m_context.push_back({CompilerContextKind::AnyDeclContext, + ConstString(scope_pair.first.str())}); + scope_pair = scope_pair.second.split("::"); + } + m_context.push_back({CompilerContextKind::AnyDeclContext, + ConstString(scope_pair.first.str())}); + } + m_context.push_back( + {ConvertTypeClass(type_class), ConstString(basename.str())}); + } else { + m_context.push_back( + {CompilerContextKind::AnyType, ConstString(name.str())}); + } +} + +TypeQuery::TypeQuery(const CompilerDeclContext &decl_ctx, + ConstString type_basename, TypeQueryOptions options) + : m_options(options) { + // Always use an exact match if we are looking for a type in compiler context. + m_options |= e_exact_match; + m_context = decl_ctx.GetCompilerContext(); + m_context.push_back({CompilerContextKind::AnyType, type_basename}); +} + +TypeQuery::TypeQuery( + const llvm::ArrayRef<lldb_private::CompilerContext> &context, + TypeQueryOptions options) + : m_context(context), m_options(options) { + // Always use an exact match if we are looking for a type in compiler context. + m_options |= e_exact_match; +} + +TypeQuery::TypeQuery(const CompilerDecl &decl, TypeQueryOptions options) + : m_options(options) { + // Always for an exact match if we are looking for a type using a declaration. + m_options |= e_exact_match; + m_context = decl.GetCompilerContext(); +} + +ConstString TypeQuery::GetTypeBasename() const { + if (m_context.empty()) + return ConstString(); + return m_context.back().name; +} + +void TypeQuery::AddLanguage(LanguageType language) { + if (!m_languages) + m_languages = LanguageSet(); + m_languages->Insert(language); +} + +bool TypeQuery::ContextMatches( + llvm::ArrayRef<CompilerContext> context_chain) const { + if (GetExactMatch() || context_chain.size() == m_context.size()) + return ::contextMatches(context_chain, m_context); + + // We don't have an exact match, we need to bottom m_context.size() items to + // match for a successful lookup. + if (context_chain.size() < m_context.size()) + return false; // Not enough items in context_chain to allow for a match. + + size_t compare_count = context_chain.size() - m_context.size(); + return ::contextMatches( + llvm::ArrayRef<CompilerContext>(context_chain.data() + compare_count, + m_context.size()), + m_context); +} + +bool TypeQuery::LanguageMatches(lldb::LanguageType language) const { + // If we have no language filterm language always matches. + if (!m_languages.has_value()) + return true; + return (*m_languages)[language]; +} + +bool TypeResults::AlreadySearched(lldb_private::SymbolFile *sym_file) { + return !m_searched_symbol_files.insert(sym_file).second; +} + +bool TypeResults::InsertUnique(const lldb::TypeSP &type_sp) { + if (type_sp) + return m_type_map.InsertUnique(type_sp); + return false; +} + +bool TypeResults::Done(const TypeQuery &query) const { + if (query.GetFindOne()) + return !m_type_map.Empty(); + return false; +} + void CompilerContext::Dump(Stream &s) const { switch (kind) { default: @@ -641,6 +762,8 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name, if (name.empty()) return false; + // Clear the scope in case we have just a type class and a basename. + scope = llvm::StringRef(); basename = name; if (basename.consume_front("struct ")) type_class = eTypeClassStruct; @@ -654,8 +777,10 @@ bool Type::GetTypeScopeAndBasename(llvm::StringRef name, type_class = eTypeClassTypedef; size_t namespace_separator = basename.find("::"); - if (namespace_separator == llvm::StringRef::npos) - return false; + if (namespace_separator == llvm::StringRef::npos) { + // If "name" started a type class we need to return true with no scope. + return type_class != eTypeClassAny; + } size_t template_begin = basename.find('<'); while (namespace_separator != llvm::StringRef::npos) { @@ -1049,16 +1174,19 @@ CompilerType TypeImpl::FindDirectNestedType(llvm::StringRef name) { return CompilerType(); auto type_system = GetTypeSystem(/*prefer_dynamic*/ false); auto *symbol_file = type_system->GetSymbolFile(); + if (!symbol_file) + return CompilerType(); auto decl_context = type_system->GetCompilerDeclContextForType(m_static_type); if (!decl_context.IsValid()) return CompilerType(); - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - TypeMap search_result; - symbol_file->FindTypes(ConstString(name), decl_context, /*max_matches*/ 1, - searched_symbol_files, search_result); - if (search_result.Empty()) - return CompilerType(); - return search_result.GetTypeAtIndex(0)->GetFullCompilerType(); + TypeQuery query(decl_context, ConstString(name), + TypeQueryOptions::e_find_one); + TypeResults results; + symbol_file->FindTypes(query, results); + TypeSP type_sp = results.GetFirstType(); + if (type_sp) + return type_sp->GetFullCompilerType(); + return CompilerType(); } bool TypeMemberFunctionImpl::IsValid() { diff --git a/lldb/source/Symbol/TypeMap.cpp b/lldb/source/Symbol/TypeMap.cpp index 0d5f6d5..8933de5 100644 --- a/lldb/source/Symbol/TypeMap.cpp +++ b/lldb/source/Symbol/TypeMap.cpp @@ -91,6 +91,12 @@ TypeSP TypeMap::GetTypeAtIndex(uint32_t idx) { return TypeSP(); } +lldb::TypeSP TypeMap::FirstType() const { + if (m_types.empty()) + return TypeSP(); + return m_types.begin()->second; +} + void TypeMap::ForEach( std::function<bool(const lldb::TypeSP &type_sp)> const &callback) const { for (auto pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { @@ -121,10 +127,10 @@ bool TypeMap::Remove(const lldb::TypeSP &type_sp) { return false; } -void TypeMap::Dump(Stream *s, bool show_context, lldb::DescriptionLevel level) { - for (iterator pos = m_types.begin(), end = m_types.end(); pos != end; ++pos) { - pos->second->Dump(s, show_context, level); - } +void TypeMap::Dump(Stream *s, bool show_context, + lldb::DescriptionLevel level) const { + for (const auto &pair : m_types) + pair.second->Dump(s, show_context, level); } void TypeMap::RemoveMismatchedTypes(llvm::StringRef type_scope, diff --git a/lldb/source/Symbol/TypeSystem.cpp b/lldb/source/Symbol/TypeSystem.cpp index 874f125..59b1b39 100644 --- a/lldb/source/Symbol/TypeSystem.cpp +++ b/lldb/source/Symbol/TypeSystem.cpp @@ -171,6 +171,16 @@ CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, return CompilerType(); } +std::vector<lldb_private::CompilerContext> +TypeSystem::DeclGetCompilerContext(void *opaque_decl) { + return {}; +} + +std::vector<lldb_private::CompilerContext> +TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) { + return {}; +} + std::vector<CompilerDecl> TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, bool ignore_imported_decls) { diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp index 42c3350..caf3e66 100644 --- a/lldb/source/Target/Language.cpp +++ b/lldb/source/Target/Language.cpp @@ -434,12 +434,10 @@ bool Language::ImageListTypeScavenger::Find_Impl( Target *target = exe_scope->CalculateTarget().get(); if (target) { const auto &images(target->GetImages()); - ConstString cs_key(key); - llvm::DenseSet<SymbolFile *> searched_sym_files; - TypeList matches; - images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files, - matches); - for (const auto &match : matches.Types()) { + TypeQuery query(key); + TypeResults type_results; + images.FindTypes(nullptr, query, type_results); + for (const auto &match : type_results.GetTypeMap().Types()) { if (match) { CompilerType compiler_type(match->GetFullCompilerType()); compiler_type = AdjustForInclusion(compiler_type); diff --git a/lldb/test/API/functionalities/type_find_first/Makefile b/lldb/test/API/functionalities/type_find_first/Makefile new file mode 100644 index 0000000..3d0b98f --- /dev/null +++ b/lldb/test/API/functionalities/type_find_first/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py new file mode 100644 index 0000000..432708d --- /dev/null +++ b/lldb/test/API/functionalities/type_find_first/TestFindFirstType.py @@ -0,0 +1,38 @@ +""" +Test the SBModule and SBTarget type lookup APIs. +""" + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TypeFindFirstTestCase(TestBase): + + NO_DEBUG_INFO_TESTCASE = True + + def test_find_first_type(self): + """ + Test SBTarget::FindFirstType() and SBModule::FindFirstType() APIs. + + This function had regressed after some past modification of the type + lookup internal code where if we had multiple types with the same + basename, FindFirstType() could end up failing depending on which + type was found first in the debug info indexes. This test will + ensure this doesn't regress in the future. + """ + self.build() + target = self.createTestTarget() + # Test the SBTarget APIs for FindFirstType + integer_type = target.FindFirstType("Integer::Point") + self.assertTrue(integer_type.IsValid()) + float_type = target.FindFirstType("Float::Point") + self.assertTrue(float_type.IsValid()) + + # Test the SBModule APIs for FindFirstType + exe_module = target.GetModuleAtIndex(0) + self.assertTrue(exe_module.IsValid()) + integer_type = exe_module.FindFirstType("Integer::Point") + self.assertTrue(integer_type.IsValid()) + float_type = exe_module.FindFirstType("Float::Point") + self.assertTrue(float_type.IsValid()) diff --git a/lldb/test/API/functionalities/type_find_first/main.cpp b/lldb/test/API/functionalities/type_find_first/main.cpp new file mode 100644 index 0000000..f4e4672 --- /dev/null +++ b/lldb/test/API/functionalities/type_find_first/main.cpp @@ -0,0 +1,17 @@ +namespace Integer { +struct Point { + int x, y; +}; +} // namespace Integer + +namespace Float { +struct Point { + float x, y; +}; +} // namespace Float + +int main(int argc, char const *argv[]) { + Integer::Point ip = {2, 3}; + Float::Point fp = {2.0, 3.0}; + return 0; +} diff --git a/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py index d9ac07f..3fa694f 100644 --- a/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py +++ b/lldb/test/API/lang/cpp/unique-types4/TestUniqueTypes4.py @@ -17,27 +17,20 @@ class UniqueTypesTestCase4(TestBase): ) # FIXME: these should successfully print the values self.expect( - "expression ns::Foo<double>::value", substrs=["no member named"], error=True + "expression ns::Foo<double>::value", substrs=["'Foo' in namespace 'ns'"], error=True ) self.expect( - "expression ns::Foo<int>::value", substrs=["no member named"], error=True + "expression ns::Foo<int>::value", substrs=["'Foo' in namespace 'ns'"], error=True ) self.expect( - "expression ns::Bar<double>::value", substrs=["no member named"], error=True + "expression ns::Bar<double>::value", substrs=["'Bar' in namespace 'ns'"], error=True ) self.expect( - "expression ns::Bar<int>::value", substrs=["no member named"], error=True - ) - self.expect( - "expression ns::FooDouble::value", - substrs=["Couldn't look up symbols"], - error=True, - ) - self.expect( - "expression ns::FooInt::value", - substrs=["Couldn't look up symbols"], - error=True, + "expression ns::Bar<int>::value", substrs=["'Bar' in namespace 'ns'"], error=True ) + self.expect_expr("ns::FooDouble::value", result_type="double", result_value="0") + self.expect_expr("ns::FooInt::value", result_type="int", result_value="0") + @skipIf(compiler=no_match("clang")) @skipIf(compiler_version=["<", "15.0"]) diff --git a/lldb/test/API/lang/cpp/unique-types4/main.cpp b/lldb/test/API/lang/cpp/unique-types4/main.cpp index 8306352..815b4f9 100644 --- a/lldb/test/API/lang/cpp/unique-types4/main.cpp +++ b/lldb/test/API/lang/cpp/unique-types4/main.cpp @@ -4,6 +4,8 @@ template <typename T> struct Foo { static T value; }; +template <class T> T Foo<T>::value = 0; + template <typename T> using Bar = Foo<T>; using FooInt = Foo<int>; @@ -20,4 +22,6 @@ ns::FooDouble f; int main() { // Set breakpoint here + return (int)a.value + b.value + (int)c.value + d.value + e.value + + (int)f.value; } diff --git a/lldb/tools/lldb-test/lldb-test.cpp b/lldb/tools/lldb-test/lldb-test.cpp index 45911b9..e326a84 100644 --- a/lldb/tools/lldb-test/lldb-test.cpp +++ b/lldb/tools/lldb-test/lldb-test.cpp @@ -290,8 +290,8 @@ int lldb_assert(Debugger &Dbg); } // namespace assert } // namespace opts -std::vector<CompilerContext> parseCompilerContext() { - std::vector<CompilerContext> result; +llvm::SmallVector<CompilerContext, 4> parseCompilerContext() { + llvm::SmallVector<CompilerContext, 4> result; if (opts::symbols::CompilerContext.empty()) return result; @@ -577,29 +577,33 @@ Error opts::symbols::findTypes(lldb_private::Module &Module) { Expected<CompilerDeclContext> ContextOr = getDeclContext(Symfile); if (!ContextOr) return ContextOr.takeError(); - const CompilerDeclContext &ContextPtr = - ContextOr->IsValid() ? *ContextOr : CompilerDeclContext(); - - LanguageSet languages; - if (!Language.empty()) - languages.Insert(Language::GetLanguageTypeFromString(Language)); - - DenseSet<SymbolFile *> SearchedFiles; - TypeMap Map; - if (!Name.empty()) - Symfile.FindTypes(ConstString(Name), ContextPtr, UINT32_MAX, SearchedFiles, - Map); - else - Module.FindTypes(parseCompilerContext(), languages, SearchedFiles, Map); - outs() << formatv("Found {0} types:\n", Map.GetSize()); + TypeResults results; + if (!Name.empty()) { + if (ContextOr->IsValid()) { + TypeQuery query(*ContextOr, ConstString(Name), + TypeQueryOptions::e_module_search); + if (!Language.empty()) + query.AddLanguage(Language::GetLanguageTypeFromString(Language)); + Symfile.FindTypes(query, results); + } else { + TypeQuery query(Name); + if (!Language.empty()) + query.AddLanguage(Language::GetLanguageTypeFromString(Language)); + Symfile.FindTypes(query, results); + } + } else { + TypeQuery query(parseCompilerContext(), TypeQueryOptions::e_module_search); + if (!Language.empty()) + query.AddLanguage(Language::GetLanguageTypeFromString(Language)); + Symfile.FindTypes(query, results); + } + outs() << formatv("Found {0} types:\n", results.GetTypeMap().GetSize()); StreamString Stream; // Resolve types to force-materialize typedef types. - Map.ForEach([&](TypeSP &type) { - type->GetFullCompilerType(); - return false; - }); - Map.Dump(&Stream, false, GetDescriptionLevel()); + for (const auto &type_sp : results.GetTypeMap().Types()) + type_sp->GetFullCompilerType(); + results.GetTypeMap().Dump(&Stream, false, GetDescriptionLevel()); outs() << Stream.GetData() << "\n"; return Error::success(); } diff --git a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h index 92bfef2..fe60481 100644 --- a/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h +++ b/llvm/include/llvm/CodeGen/CodeGenPassBuilder.h @@ -48,6 +48,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Target/CGPassBuilderOption.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Transforms/CFGuard.h" #include "llvm/Transforms/Scalar/ConstantHoisting.h" #include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Scalar/LoopStrengthReduce.h" diff --git a/llvm/include/llvm/CodeGen/MachinePassRegistry.def b/llvm/include/llvm/CodeGen/MachinePassRegistry.def index 9ebf33b..283fb14 100644 --- a/llvm/include/llvm/CodeGen/MachinePassRegistry.def +++ b/llvm/include/llvm/CodeGen/MachinePassRegistry.def @@ -38,6 +38,7 @@ FUNCTION_ANALYSIS("targetir", TargetIRAnalysis, #define FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) #endif FUNCTION_PASS("callbrprepare", CallBrPreparePass, ()) +FUNCTION_PASS("cfguard", CFGuardPass, ()) FUNCTION_PASS("consthoist", ConstantHoistingPass, ()) FUNCTION_PASS("dwarf-eh-prepare", DwarfEHPreparePass, (TM)) FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass, (false)) @@ -124,8 +125,6 @@ MACHINE_FUNCTION_ANALYSIS("pass-instrumentation", PassInstrumentationAnalysis, #define DUMMY_FUNCTION_PASS(NAME, PASS_NAME, CONSTRUCTOR) #endif DUMMY_FUNCTION_PASS("atomic-expand", AtomicExpandPass, ()) -DUMMY_FUNCTION_PASS("cfguard-check", CFGuardCheckPass, ()) -DUMMY_FUNCTION_PASS("cfguard-dispatch", CFGuardDispatchPass, ()) DUMMY_FUNCTION_PASS("codegenprepare", CodeGenPreparePass, ()) DUMMY_FUNCTION_PASS("expandmemcmp", ExpandMemCmpPass, ()) DUMMY_FUNCTION_PASS("gc-lowering", GCLoweringPass, ()) diff --git a/llvm/include/llvm/Transforms/CFGuard.h b/llvm/include/llvm/Transforms/CFGuard.h index 86fcbc3..caf822a2 100644 --- a/llvm/include/llvm/Transforms/CFGuard.h +++ b/llvm/include/llvm/Transforms/CFGuard.h @@ -11,10 +11,23 @@ #ifndef LLVM_TRANSFORMS_CFGUARD_H #define LLVM_TRANSFORMS_CFGUARD_H +#include "llvm/IR/PassManager.h" + namespace llvm { class FunctionPass; +class CFGuardPass : public PassInfoMixin<CFGuardPass> { +public: + enum class Mechanism { Check, Dispatch }; + + CFGuardPass(Mechanism M = Mechanism::Check) : GuardMechanism(M) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); + +private: + Mechanism GuardMechanism; +}; + /// Insert Control FLow Guard checks on indirect function calls. FunctionPass *createCFGuardCheckPass(); diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt index e42edfe..98d2de7 100644 --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -16,6 +16,7 @@ add_llvm_component_library(LLVMPasses LINK_COMPONENTS AggressiveInstCombine Analysis + CFGuard CodeGen Core Coroutines diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index c48e591..f0417d6 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -100,6 +100,7 @@ #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" +#include "llvm/Transforms/CFGuard.h" #include "llvm/Transforms/Coroutines/CoroCleanup.h" #include "llvm/Transforms/Coroutines/CoroConditionalWrapper.h" #include "llvm/Transforms/Coroutines/CoroEarly.h" @@ -738,6 +739,26 @@ Expected<bool> parsePostOrderFunctionAttrsPassOptions(StringRef Params) { "PostOrderFunctionAttrs"); } +Expected<CFGuardPass::Mechanism> parseCFGuardPassOptions(StringRef Params) { + if (Params.empty()) + return CFGuardPass::Mechanism::Check; + + auto [Param, RHS] = Params.split(';'); + if (!RHS.empty()) + return make_error<StringError>( + formatv("too many CFGuardPass parameters '{0}' ", Params).str(), + inconvertibleErrorCode()); + + if (Param == "check") + return CFGuardPass::Mechanism::Check; + if (Param == "dispatch") + return CFGuardPass::Mechanism::Dispatch; + + return make_error<StringError>( + formatv("invalid CFGuardPass mechanism: '{0}' ", Param).str(), + inconvertibleErrorCode()); +} + Expected<bool> parseEarlyCSEPassOptions(StringRef Params) { return parseSinglePassOption(Params, "memssa", "EarlyCSE"); } diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 6afc8b4..1a9a348 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -434,6 +434,10 @@ FUNCTION_PASS("wasm-eh-prepare", WasmEHPreparePass()) #define FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, PARAMS) #endif FUNCTION_PASS_WITH_PARAMS( + "cfguard", "CFGuardPass", + [](CFGuardPass::Mechanism M) { return CFGuardPass(M); }, + parseCFGuardPassOptions, "check;dispatch") +FUNCTION_PASS_WITH_PARAMS( "early-cse", "EarlyCSEPass", [](bool UseMemorySSA) { return EarlyCSEPass(UseMemorySSA); }, parseEarlyCSEPassOptions, "memssa") diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 246f6b4..5428e14 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -55,6 +55,8 @@ bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const { // We should properly mark well-known section name prefixes as small/large, // because otherwise the output section may have the wrong section flags and // the linker will lay it out in an unexpected way. + // TODO: bring back lbss/ldata/lrodata checks after fixing accesses to large + // globals in the small code model. StringRef Name = GV->getSection(); if (!Name.empty()) { auto IsPrefix = [&](StringRef Prefix) { @@ -63,8 +65,6 @@ bool TargetMachine::isLargeGlobalObject(const GlobalObject *GO) const { }; if (IsPrefix(".bss") || IsPrefix(".data") || IsPrefix(".rodata")) return false; - if (IsPrefix(".lbss") || IsPrefix(".ldata") || IsPrefix(".lrodata")) - return true; } // For x86-64, we treat an explicit GlobalVariable small code model to mean diff --git a/llvm/lib/Transforms/CFGuard/CFGuard.cpp b/llvm/lib/Transforms/CFGuard/CFGuard.cpp index 3877343..4d43065 100644 --- a/llvm/lib/Transforms/CFGuard/CFGuard.cpp +++ b/llvm/lib/Transforms/CFGuard/CFGuard.cpp @@ -34,25 +34,22 @@ namespace { /// Adds Control Flow Guard (CFG) checks on indirect function calls/invokes. /// These checks ensure that the target address corresponds to the start of an -/// address-taken function. X86_64 targets use the CF_Dispatch mechanism. X86, -/// ARM, and AArch64 targets use the CF_Check machanism. -class CFGuard : public FunctionPass { +/// address-taken function. X86_64 targets use the Mechanism::Dispatch +/// mechanism. X86, ARM, and AArch64 targets use the Mechanism::Check machanism. +class CFGuardImpl { public: - static char ID; - - enum Mechanism { CF_Check, CF_Dispatch }; - - // Default constructor required for the INITIALIZE_PASS macro. - CFGuard() : FunctionPass(ID) { - initializeCFGuardPass(*PassRegistry::getPassRegistry()); - // By default, use the guard check mechanism. - GuardMechanism = CF_Check; - } - - // Recommended constructor used to specify the type of guard mechanism. - CFGuard(Mechanism Var) : FunctionPass(ID) { - initializeCFGuardPass(*PassRegistry::getPassRegistry()); - GuardMechanism = Var; + using Mechanism = CFGuardPass::Mechanism; + + CFGuardImpl(Mechanism M) : GuardMechanism(M) { + // Get or insert the guard check or dispatch global symbols. + switch (GuardMechanism) { + case Mechanism::Check: + GuardFnName = "__guard_check_icall_fptr"; + break; + case Mechanism::Dispatch: + GuardFnName = "__guard_dispatch_icall_fptr"; + break; + } } /// Inserts a Control Flow Guard (CFG) check on an indirect call using the CFG @@ -141,21 +138,37 @@ public: /// \param CB indirect call to instrument. void insertCFGuardDispatch(CallBase *CB); - bool doInitialization(Module &M) override; - bool runOnFunction(Function &F) override; + bool doInitialization(Module &M); + bool runOnFunction(Function &F); private: // Only add checks if the module has the cfguard=2 flag. int cfguard_module_flag = 0; - Mechanism GuardMechanism = CF_Check; + StringRef GuardFnName; + Mechanism GuardMechanism = Mechanism::Check; FunctionType *GuardFnType = nullptr; PointerType *GuardFnPtrType = nullptr; Constant *GuardFnGlobal = nullptr; }; +class CFGuard : public FunctionPass { + CFGuardImpl Impl; + +public: + static char ID; + + // Default constructor required for the INITIALIZE_PASS macro. + CFGuard(CFGuardImpl::Mechanism M) : FunctionPass(ID), Impl(M) { + initializeCFGuardPass(*PassRegistry::getPassRegistry()); + } + + bool doInitialization(Module &M) override { return Impl.doInitialization(M); } + bool runOnFunction(Function &F) override { return Impl.runOnFunction(F); } +}; + } // end anonymous namespace -void CFGuard::insertCFGuardCheck(CallBase *CB) { +void CFGuardImpl::insertCFGuardCheck(CallBase *CB) { assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() && "Only applicable for Windows targets"); @@ -184,7 +197,7 @@ void CFGuard::insertCFGuardCheck(CallBase *CB) { GuardCheck->setCallingConv(CallingConv::CFGuard_Check); } -void CFGuard::insertCFGuardDispatch(CallBase *CB) { +void CFGuardImpl::insertCFGuardDispatch(CallBase *CB) { assert(Triple(CB->getModule()->getTargetTriple()).isOSWindows() && "Only applicable for Windows targets"); @@ -218,7 +231,7 @@ void CFGuard::insertCFGuardDispatch(CallBase *CB) { CB->eraseFromParent(); } -bool CFGuard::doInitialization(Module &M) { +bool CFGuardImpl::doInitialization(Module &M) { // Check if this module has the cfguard flag and read its value. if (auto *MD = @@ -235,15 +248,6 @@ bool CFGuard::doInitialization(Module &M) { {PointerType::getUnqual(M.getContext())}, false); GuardFnPtrType = PointerType::get(GuardFnType, 0); - // Get or insert the guard check or dispatch global symbols. - llvm::StringRef GuardFnName; - if (GuardMechanism == CF_Check) { - GuardFnName = "__guard_check_icall_fptr"; - } else if (GuardMechanism == CF_Dispatch) { - GuardFnName = "__guard_dispatch_icall_fptr"; - } else { - assert(false && "Invalid CFGuard mechanism"); - } GuardFnGlobal = M.getOrInsertGlobal(GuardFnName, GuardFnPtrType, [&] { auto *Var = new GlobalVariable(M, GuardFnPtrType, false, GlobalVariable::ExternalLinkage, nullptr, @@ -255,7 +259,7 @@ bool CFGuard::doInitialization(Module &M) { return true; } -bool CFGuard::runOnFunction(Function &F) { +bool CFGuardImpl::runOnFunction(Function &F) { // Skip modules for which CFGuard checks have been disabled. if (cfguard_module_flag != 2) @@ -283,7 +287,7 @@ bool CFGuard::runOnFunction(Function &F) { } // For each indirect call/invoke, add the appropriate dispatch or check. - if (GuardMechanism == CF_Dispatch) { + if (GuardMechanism == Mechanism::Dispatch) { for (CallBase *CB : IndirectCalls) { insertCFGuardDispatch(CB); } @@ -296,13 +300,20 @@ bool CFGuard::runOnFunction(Function &F) { return true; } +PreservedAnalyses CFGuardPass::run(Function &F, FunctionAnalysisManager &FAM) { + CFGuardImpl Impl(GuardMechanism); + bool Changed = Impl.doInitialization(*F.getParent()); + Changed |= Impl.runOnFunction(F); + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} + char CFGuard::ID = 0; INITIALIZE_PASS(CFGuard, "CFGuard", "CFGuard", false, false) FunctionPass *llvm::createCFGuardCheckPass() { - return new CFGuard(CFGuard::CF_Check); + return new CFGuard(CFGuardPass::Mechanism::Check); } FunctionPass *llvm::createCFGuardDispatchPass() { - return new CFGuard(CFGuard::CF_Dispatch); + return new CFGuard(CFGuardPass::Mechanism::Dispatch); } diff --git a/llvm/test/CodeGen/X86/code-model-elf-sections.ll b/llvm/test/CodeGen/X86/code-model-elf-sections.ll index 749d5b6b..cb19f0d 100644 --- a/llvm/test/CodeGen/X86/code-model-elf-sections.ll +++ b/llvm/test/CodeGen/X86/code-model-elf-sections.ll @@ -21,16 +21,16 @@ ; SMALL: .data {{.*}} WA {{.*}} ; SMALL: .data.x {{.*}} WA {{.*}} ; SMALL: .data0 {{.*}} WA {{.*}} -; SMALL: .ldata {{.*}} WAl {{.*}} -; SMALL: .ldata.x {{.*}} WAl {{.*}} +; SMALL: .ldata {{.*}} WA {{.*}} +; SMALL: .ldata.x {{.*}} WA {{.*}} ; SMALL: .ldata0 {{.*}} WA {{.*}} ; SMALL: force_small {{.*}} WA {{.*}} ; SMALL: force_large {{.*}} WAl {{.*}} ; SMALL: foo {{.*}} WA {{.*}} ; SMALL: .bss {{.*}} WA {{.*}} -; SMALL: .lbss {{.*}} WAl {{.*}} +; SMALL: .lbss {{.*}} WA {{.*}} ; SMALL: .rodata {{.*}} A {{.*}} -; SMALL: .lrodata {{.*}} Al {{.*}} +; SMALL: .lrodata {{.*}} A {{.*}} ; SMALL: .data.rel.ro {{.*}} WA {{.*}} ; SMALL: .tbss {{.*}} WAT {{.*}} ; SMALL: .tdata {{.*}} WAT {{.*}} @@ -38,16 +38,16 @@ ; SMALL-DS: .data {{.*}} WA {{.*}} ; SMALL-DS: .data.x {{.*}} WA {{.*}} ; SMALL-DS: .data0 {{.*}} WA {{.*}} -; SMALL-DS: .ldata {{.*}} WAl {{.*}} -; SMALL-DS: .ldata.x {{.*}} WAl {{.*}} +; SMALL-DS: .ldata {{.*}} WA {{.*}} +; SMALL-DS: .ldata.x {{.*}} WA {{.*}} ; SMALL-DS: .ldata0 {{.*}} WA {{.*}} ; SMALL-DS: .data.data {{.*}} WA {{.*}} ; SMALL-DS: force_small {{.*}} WA {{.*}} ; SMALL-DS: force_large {{.*}} WAl {{.*}} ; SMALL-DS: foo {{.*}} WA {{.*}} -; SMALL-DS: .lbss {{.*}} WAl {{.*}} +; SMALL-DS: .lbss {{.*}} WA {{.*}} ; SMALL-DS: .bss.bss {{.*}} WA {{.*}} -; SMALL-DS: .lrodata {{.*}} Al {{.*}} +; SMALL-DS: .lrodata {{.*}} A {{.*}} ; SMALL-DS: .rodata.rodata {{.*}} A {{.*}} ; SMALL-DS: .data.rel.ro.relro {{.*}} WA {{.*}} ; SMALL-DS: .tbss.tbss {{.*}} WAT {{.*}} diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/CMakeLists.txt b/mlir/lib/Dialect/SparseTensor/Transforms/CMakeLists.txt index 8459e46..ad8b0d0 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/CMakeLists.txt +++ b/mlir/lib/Dialect/SparseTensor/Transforms/CMakeLists.txt @@ -1,9 +1,6 @@ add_mlir_dialect_library(MLIRSparseTensorTransforms + # Rewriting. BufferizableOpInterfaceImpl.cpp - CodegenEnv.cpp - CodegenUtils.cpp - IterationGraphSorter.cpp - LoopEmitter.cpp SparseBufferRewriting.cpp SparseGPUCodegen.cpp SparseReinterpretMap.cpp @@ -12,11 +9,16 @@ add_mlir_dialect_library(MLIRSparseTensorTransforms SparseTensorConversion.cpp SparseTensorPasses.cpp SparseTensorRewriting.cpp - SparseTensorDescriptor.cpp SparseVectorization.cpp Sparsification.cpp SparsificationAndBufferizationPass.cpp StageSparseOperations.cpp + # Utilities. + Utils/CodegenEnv.cpp + Utils/CodegenUtils.cpp + Utils/IterationGraphSorter.cpp + Utils/LoopEmitter.cpp + Utils/SparseTensorDescriptor.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/SparseTensor diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseBufferRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseBufferRewriting.cpp index cdbf4f0..248e941 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseBufferRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseBufferRewriting.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" +#include "Utils/CodegenUtils.h" #include "mlir/Dialect/Arith/IR/Arith.h" #include "mlir/Dialect/Func/IR/FuncOps.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseGPUCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseGPUCodegen.cpp index 5155cab..477ff2e 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseGPUCodegen.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseGPUCodegen.cpp @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" -#include "LoopEmitter.h" +#include "Utils/CodegenUtils.h" +#include "Utils/LoopEmitter.h" #include "mlir/Dialect/Bufferization/IR/Bufferization.h" #include "mlir/Dialect/GPU/IR/GPUDialect.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp index 488079c..f2e1b0b 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseReinterpretMap.cpp @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" -#include "IterationGraphSorter.h" +#include "Utils/CodegenUtils.h" +#include "Utils/IterationGraphSorter.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Bufferization/IR/Bufferization.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp index a6f4dd3..91dad05 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseStorageSpecifierToLLVM.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" +#include "Utils/CodegenUtils.h" #include "mlir/Conversion/LLVMCommon/StructBuilder.h" #include "mlir/Dialect/SparseTensor/IR/SparseTensorStorageLayout.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp index 18b2bb0..491501a 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorCodegen.cpp @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" -#include "SparseTensorDescriptor.h" +#include "Utils/CodegenUtils.h" +#include "Utils/SparseTensorDescriptor.h" #include "mlir/Dialect/Arith/Utils/Utils.h" #include "mlir/Dialect/Bufferization/IR/Bufferization.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp index e6052f2..b0447b2 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorConversion.cpp @@ -16,7 +16,7 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" +#include "Utils/CodegenUtils.h" #include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h" #include "mlir/Dialect/Bufferization/IR/Bufferization.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp index 4fc692f..3b9685b 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorRewriting.cpp @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" -#include "LoopEmitter.h" +#include "Utils/CodegenUtils.h" +#include "Utils/LoopEmitter.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseVectorization.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/SparseVectorization.cpp index 561c4e2..7710a44 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseVectorization.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/SparseVectorization.cpp @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#include "CodegenUtils.h" -#include "LoopEmitter.h" +#include "Utils/CodegenUtils.h" +#include "Utils/LoopEmitter.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp index 2367d3b..934e1e5 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Sparsification.cpp @@ -10,9 +10,9 @@ // //===----------------------------------------------------------------------===// -#include "CodegenEnv.h" -#include "CodegenUtils.h" -#include "LoopEmitter.h" +#include "Utils/CodegenEnv.h" +#include "Utils/CodegenUtils.h" +#include "Utils/LoopEmitter.h" #include "mlir/Dialect/Affine/IR/AffineOps.h" #include "mlir/Dialect/Arith/IR/Arith.h" diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenEnv.cpp index 4bd3af2..4bd3af2 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenEnv.cpp diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenEnv.h index cd626041..cd626041 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenEnv.h +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenEnv.h diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp index 33d449a..33d449a 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.cpp diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h index 57de437..57de437 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/CodegenUtils.h +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/CodegenUtils.h diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/IterationGraphSorter.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/IterationGraphSorter.cpp index b601172..b601172 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/IterationGraphSorter.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/IterationGraphSorter.cpp diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/IterationGraphSorter.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/IterationGraphSorter.h index 52ee117..52ee117 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/IterationGraphSorter.h +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/IterationGraphSorter.h diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/LoopEmitter.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/LoopEmitter.cpp index 08d37b6..08d37b6 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/LoopEmitter.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/LoopEmitter.cpp diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/LoopEmitter.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/LoopEmitter.h index fa8b007..fa8b007 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/LoopEmitter.h +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/LoopEmitter.h diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorDescriptor.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/SparseTensorDescriptor.cpp index 3ab4157..3ab4157 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorDescriptor.cpp +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/SparseTensorDescriptor.cpp diff --git a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorDescriptor.h b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/SparseTensorDescriptor.h index 5c7d8aa..5c7d8aa 100644 --- a/mlir/lib/Dialect/SparseTensor/Transforms/SparseTensorDescriptor.h +++ b/mlir/lib/Dialect/SparseTensor/Transforms/Utils/SparseTensorDescriptor.h diff --git a/mlir/tools/mlir-opt/CMakeLists.txt b/mlir/tools/mlir-opt/CMakeLists.txt index bc8eed1..b6ada66 100644 --- a/mlir/tools/mlir-opt/CMakeLists.txt +++ b/mlir/tools/mlir-opt/CMakeLists.txt @@ -67,6 +67,10 @@ set(LIBS MLIRTransformUtils MLIRSupport MLIRIR + + # TODO: Remove when registerAllGPUToLLVMIRTranslations is no longer + # registered directly in mlir-opt.cpp. + MLIRToLLVMIRTranslationRegistration ) # Exclude from libMLIR.so because this has static options intended for diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp index c7cf1e5..b7c69ea 100644 --- a/mlir/tools/mlir-opt/mlir-opt.cpp +++ b/mlir/tools/mlir-opt/mlir-opt.cpp @@ -276,6 +276,10 @@ int main(int argc, char **argv) { DialectRegistry registry; registerAllDialects(registry); registerAllExtensions(registry); + + // TODO: Remove this and the corresponding MLIRToLLVMIRTranslationRegistration + // cmake dependency when a safe dialect interface registration mechanism is + // implemented, see D157703 (and corresponding note on the declaration). registerAllGPUToLLVMIRTranslations(registry); #ifdef MLIR_INCLUDE_TESTS diff --git a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel index 2e3bb8a..200998a 100644 --- a/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/mlir/BUILD.bazel @@ -2773,13 +2773,9 @@ cc_library( td_library( name = "SparseTensorTdFiles", - srcs = [ - "include/mlir/Dialect/SparseTensor/IR/SparseTensorAttrDefs.td", - "include/mlir/Dialect/SparseTensor/IR/SparseTensorBase.td", - "include/mlir/Dialect/SparseTensor/IR/SparseTensorInterfaces.td", - "include/mlir/Dialect/SparseTensor/IR/SparseTensorOps.td", - "include/mlir/Dialect/SparseTensor/IR/SparseTensorTypes.td", - ], + srcs = glob([ + "include/mlir/Dialect/SparseTensor/IR/*.td", + ]), includes = ["include"], deps = [ ":InferTypeOpInterfaceTdFiles", @@ -2788,15 +2784,6 @@ td_library( ], ) -td_library( - name = "SparseTensorInterfacesTdFiles", - srcs = [ - "include/mlir/Dialect/SparseTensor/IR/SparseTensorInterfaces.td", - ], - includes = ["include"], - deps = [":OpBaseTdFiles"], -) - gentbl_cc_library( name = "SparseTensorAttrDefsIncGen", tbl_outs = [ @@ -2918,7 +2905,37 @@ gentbl_cc_library( ], tblgen = ":mlir-tblgen", td_file = "include/mlir/Dialect/SparseTensor/IR/SparseTensorInterfaces.td", - deps = [":SparseTensorInterfacesTdFiles"], + deps = [":SparseTensorTdFiles"], +) + +td_library( + name = "SparseTensorTransformOpsTdFiles", + srcs = glob([ + "include/mlir/Dialect/SparseTensor/TransformOps/*.td", + ]), + includes = ["include"], + deps = [ + ":TransformDialectTdFiles", + ], +) + +gentbl_cc_library( + name = "SparseTensorTransformOpsIncGen", + tbl_outs = [ + ( + ["-gen-op-decls"], + "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h.inc", + ), + ( + ["-gen-op-defs"], + "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.cpp.inc", + ), + ], + tblgen = ":mlir-tblgen", + td_file = "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td", + deps = [ + ":SparseTensorTransformOpsTdFiles", + ], ) # This library is shared by both SparseTensorDialect and @@ -2932,19 +2949,11 @@ cc_library( cc_library( name = "SparseTensorDialect", - srcs = [ - "lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.cpp", - "lib/Dialect/SparseTensor/IR/Detail/DimLvlMap.h", - "lib/Dialect/SparseTensor/IR/Detail/DimLvlMapParser.cpp", - "lib/Dialect/SparseTensor/IR/Detail/DimLvlMapParser.h", - "lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.cpp", - "lib/Dialect/SparseTensor/IR/Detail/LvlTypeParser.h", - "lib/Dialect/SparseTensor/IR/Detail/TemplateExtras.h", - "lib/Dialect/SparseTensor/IR/Detail/Var.cpp", - "lib/Dialect/SparseTensor/IR/Detail/Var.h", - "lib/Dialect/SparseTensor/IR/SparseTensorDialect.cpp", - "lib/Dialect/SparseTensor/IR/SparseTensorInterfaces.cpp", - ], + srcs = glob([ + "lib/Dialect/SparseTensor/IR/*.cpp", + "lib/Dialect/SparseTensor/IR/Detail/*.cpp", + "lib/Dialect/SparseTensor/IR/Detail/*.h", + ]), hdrs = [ "include/mlir/Dialect/SparseTensor/IR/SparseTensor.h", "include/mlir/Dialect/SparseTensor/IR/SparseTensorInterfaces.h", @@ -2987,40 +2996,14 @@ cc_library( ], ) -td_library( - name = "SparseTensorTransformOpsTdFiles", - srcs = glob([ - "include/mlir/Dialect/SparseTensor/TransformOps/*.td", - ]), - includes = ["include"], - deps = [ - ":TransformDialectTdFiles", - ], -) - -gentbl_cc_library( - name = "SparseTensorTransformOpsIncGen", - tbl_outs = [ - ( - ["-gen-op-decls"], - "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.h.inc", - ), - ( - ["-gen-op-defs"], - "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.cpp.inc", - ), - ], - tblgen = ":mlir-tblgen", - td_file = "include/mlir/Dialect/SparseTensor/TransformOps/SparseTensorTransformOps.td", - deps = [ - ":SparseTensorTransformOpsTdFiles", - ], -) - cc_library( name = "SparseTensorUtils", - srcs = glob(["lib/Dialect/SparseTensor/Utils/*.cpp"]), - hdrs = glob(["include/mlir/Dialect/SparseTensor/Utils/*.h"]), + srcs = glob([ + "lib/Dialect/SparseTensor/Utils/*.cpp", + ]), + hdrs = glob([ + "include/mlir/Dialect/SparseTensor/Utils/*.h", + ]), includes = ["include"], deps = [ ":ArithDialect", @@ -3039,6 +3022,8 @@ cc_library( srcs = glob([ "lib/Dialect/SparseTensor/Transforms/*.cpp", "lib/Dialect/SparseTensor/Transforms/*.h", + "lib/Dialect/SparseTensor/Transforms/Utils/*.cpp", + "lib/Dialect/SparseTensor/Transforms/Utils/*.h", ]), hdrs = [ "include/mlir/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.h", @@ -3081,8 +3066,12 @@ cc_library( cc_library( name = "SparseTensorPipelines", - srcs = glob(["lib/Dialect/SparseTensor/Pipelines/*.cpp"]), - hdrs = ["include/mlir/Dialect/SparseTensor/Pipelines/Passes.h"], + srcs = glob([ + "lib/Dialect/SparseTensor/Pipelines/*.cpp", + ]), + hdrs = [ + "include/mlir/Dialect/SparseTensor/Pipelines/Passes.h", + ], includes = ["include"], local_defines = if_cuda_available(["MLIR_GPU_TO_CUBIN_PASS_ENABLE"]), deps = [ |