diff options
Diffstat (limited to 'include/lldb/Symbol/ClangASTImporter.h')
-rw-r--r-- | include/lldb/Symbol/ClangASTImporter.h | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h new file mode 100644 index 0000000000000..10df7da893a84 --- /dev/null +++ b/include/lldb/Symbol/ClangASTImporter.h @@ -0,0 +1,371 @@ +//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTImporter_h_ +#define liblldb_ClangASTImporter_h_ + +#include <map> +#include <set> + +#include "lldb/lldb-types.h" +#include "clang/AST/ASTImporter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" + +namespace lldb_private { + +class ClangASTMetrics +{ +public: + static void DumpCounters (Log *log); + static void ClearLocalCounters () + { + local_counters = { 0, 0, 0, 0, 0, 0 }; + } + + static void RegisterVisibleQuery () + { + ++global_counters.m_visible_query_count; + ++local_counters.m_visible_query_count; + } + + static void RegisterLexicalQuery () + { + ++global_counters.m_lexical_query_count; + ++local_counters.m_lexical_query_count; + } + + static void RegisterLLDBImport () + { + ++global_counters.m_lldb_import_count; + ++local_counters.m_lldb_import_count; + } + + static void RegisterClangImport () + { + ++global_counters.m_clang_import_count; + ++local_counters.m_clang_import_count; + } + + static void RegisterDeclCompletion () + { + ++global_counters.m_decls_completed_count; + ++local_counters.m_decls_completed_count; + } + + static void RegisterRecordLayout () + { + ++global_counters.m_record_layout_count; + ++local_counters.m_record_layout_count; + } + +private: + struct Counters + { + uint64_t m_visible_query_count; + uint64_t m_lexical_query_count; + uint64_t m_lldb_import_count; + uint64_t m_clang_import_count; + uint64_t m_decls_completed_count; + uint64_t m_record_layout_count; + }; + + static Counters global_counters; + static Counters local_counters; + + static void DumpCounters (Log *log, Counters &counters); +}; + +class ClangASTImporter +{ +public: + ClangASTImporter () : + m_file_manager(clang::FileSystemOptions()) + { + } + + clang::QualType + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::QualType type); + + lldb::clang_type_t + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + CopyDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + lldb::clang_type_t + DeportType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + DeportDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + void + CompleteDecl (clang::Decl *decl); + + bool + CompleteTagDecl (clang::TagDecl *decl); + + bool + CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin); + + bool + CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl); + + bool + RequireCompleteType (clang::QualType type); + + bool + ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx) + { + DeclOrigin origin = GetDeclOrigin(decl); + + if (original_decl) + *original_decl = origin.decl; + + if (original_ctx) + *original_ctx = origin.ctx; + + return origin.Valid(); + } + + void + SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl); + + ClangASTMetadata * + GetDeclMetadata (const clang::Decl *decl); + + // + // Namespace maps + // + + typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap; + typedef std::shared_ptr<NamespaceMap> NamespaceMapSP; + + void RegisterNamespaceMap (const clang::NamespaceDecl *decl, + NamespaceMapSP &namespace_map); + + NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl); + + void BuildNamespaceMap (const clang::NamespaceDecl *decl); + + // + // Comleters for maps + // + + class MapCompleter + { + public: + virtual ~MapCompleter (); + + virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map, + const ConstString &name, + NamespaceMapSP &parent_map) const = 0; + }; + + void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer) + { + ASTContextMetadataSP context_md; + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + } + else + { + context_md = context_md_iter->second; + } + + context_md->m_map_completer = &completer; + } + + void ForgetDestination (clang::ASTContext *dst_ctx); + void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); +private: + struct DeclOrigin + { + DeclOrigin () : + ctx(NULL), + decl(NULL) + { + } + + DeclOrigin (clang::ASTContext *_ctx, + clang::Decl *_decl) : + ctx(_ctx), + decl(_decl) + { + } + + DeclOrigin (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + void operator= (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + bool + Valid () + { + return (ctx != NULL || decl != NULL); + } + + clang::ASTContext *ctx; + clang::Decl *decl; + }; + + typedef std::map<const clang::Decl *, DeclOrigin> OriginMap; + + class Minion : public clang::ASTImporter + { + public: + Minion (ClangASTImporter &master, + clang::ASTContext *target_ctx, + clang::ASTContext *source_ctx) : + clang::ASTImporter(*target_ctx, + master.m_file_manager, + *source_ctx, + master.m_file_manager, + true /*minimal*/), + m_decls_to_deport(NULL), + m_decls_already_deported(NULL), + m_master(master), + m_source_ctx(source_ctx) + { + } + + // A call to "InitDeportWorkQueues" puts the minion into deport mode. + // In deport mode, every copied Decl that could require completion is + // recorded and placed into the decls_to_deport set. + // + // A call to "ExecuteDeportWorkQueues" completes all the Decls that + // are in decls_to_deport, adding any Decls it sees along the way that + // it hasn't already deported. It proceeds until decls_to_deport is + // empty. + // + // These calls must be paired. Leaving a minion in deport mode or + // trying to start deport minion with a new pair of queues will result + // in an assertion failure. + + void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport, + std::set<clang::NamedDecl *> *decls_already_deported); + void ExecuteDeportWorkQueues (); + + void ImportDefinitionTo (clang::Decl *to, clang::Decl *from); + + clang::Decl *Imported (clang::Decl *from, clang::Decl *to); + + std::set<clang::NamedDecl *> *m_decls_to_deport; + std::set<clang::NamedDecl *> *m_decls_already_deported; + ClangASTImporter &m_master; + clang::ASTContext *m_source_ctx; + }; + + typedef std::shared_ptr<Minion> MinionSP; + typedef std::map<clang::ASTContext *, MinionSP> MinionMap; + typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap; + + struct ASTContextMetadata + { + ASTContextMetadata(clang::ASTContext *dst_ctx) : + m_dst_ctx (dst_ctx), + m_minions (), + m_origins (), + m_namespace_maps (), + m_map_completer (NULL) + { + } + + clang::ASTContext *m_dst_ctx; + MinionMap m_minions; + OriginMap m_origins; + + NamespaceMetaMap m_namespace_maps; + MapCompleter *m_map_completer; + }; + + typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP; + typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap; + + ContextMetadataMap m_metadata_map; + + ASTContextMetadataSP + GetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + return context_md; + } + else + { + return context_md_iter->second; + } + } + + ASTContextMetadataSP + MaybeGetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter != m_metadata_map.end()) + return context_md_iter->second; + else + return ASTContextMetadataSP(); + } + + MinionSP + GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) + { + ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx); + + MinionMap &minions = context_md->m_minions; + MinionMap::iterator minion_iter = minions.find(src_ctx); + + if (minion_iter == minions.end()) + { + MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx)); + minions[src_ctx] = minion; + return minion; + } + else + { + return minion_iter->second; + } + } + + DeclOrigin + GetDeclOrigin (const clang::Decl *decl); + + clang::FileManager m_file_manager; +}; + +} + +#endif |