ClangASTImporter.h revision 344779
1//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef liblldb_ClangASTImporter_h_ 11#define liblldb_ClangASTImporter_h_ 12 13#include <map> 14#include <memory> 15#include <set> 16#include <vector> 17 18#include "clang/AST/ASTImporter.h" 19#include "clang/AST/CharUnits.h" 20#include "clang/AST/Decl.h" 21#include "clang/AST/DeclCXX.h" 22#include "clang/Basic/FileManager.h" 23#include "clang/Basic/FileSystemOptions.h" 24 25#include "lldb/Symbol/CompilerDeclContext.h" 26#include "lldb/lldb-types.h" 27 28#include "llvm/ADT/DenseMap.h" 29 30namespace lldb_private { 31 32class ClangASTMetrics { 33public: 34 static void DumpCounters(Log *log); 35 static void ClearLocalCounters() { local_counters = {0, 0, 0, 0, 0, 0}; } 36 37 static void RegisterVisibleQuery() { 38 ++global_counters.m_visible_query_count; 39 ++local_counters.m_visible_query_count; 40 } 41 42 static void RegisterLexicalQuery() { 43 ++global_counters.m_lexical_query_count; 44 ++local_counters.m_lexical_query_count; 45 } 46 47 static void RegisterLLDBImport() { 48 ++global_counters.m_lldb_import_count; 49 ++local_counters.m_lldb_import_count; 50 } 51 52 static void RegisterClangImport() { 53 ++global_counters.m_clang_import_count; 54 ++local_counters.m_clang_import_count; 55 } 56 57 static void RegisterDeclCompletion() { 58 ++global_counters.m_decls_completed_count; 59 ++local_counters.m_decls_completed_count; 60 } 61 62 static void RegisterRecordLayout() { 63 ++global_counters.m_record_layout_count; 64 ++local_counters.m_record_layout_count; 65 } 66 67private: 68 struct Counters { 69 uint64_t m_visible_query_count; 70 uint64_t m_lexical_query_count; 71 uint64_t m_lldb_import_count; 72 uint64_t m_clang_import_count; 73 uint64_t m_decls_completed_count; 74 uint64_t m_record_layout_count; 75 }; 76 77 static Counters global_counters; 78 static Counters local_counters; 79 80 static void DumpCounters(Log *log, Counters &counters); 81}; 82 83class ClangASTImporter { 84public: 85 struct LayoutInfo { 86 LayoutInfo() 87 : bit_size(0), alignment(0), field_offsets(), base_offsets(), 88 vbase_offsets() {} 89 uint64_t bit_size; 90 uint64_t alignment; 91 llvm::DenseMap<const clang::FieldDecl *, uint64_t> field_offsets; 92 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> base_offsets; 93 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 94 vbase_offsets; 95 }; 96 97 ClangASTImporter() : m_file_manager(clang::FileSystemOptions()) {} 98 99 clang::QualType CopyType(clang::ASTContext *dst_ctx, 100 clang::ASTContext *src_ctx, clang::QualType type); 101 102 lldb::opaque_compiler_type_t CopyType(clang::ASTContext *dst_ctx, 103 clang::ASTContext *src_ctx, 104 lldb::opaque_compiler_type_t type); 105 106 CompilerType CopyType(ClangASTContext &dst, const CompilerType &src_type); 107 108 clang::Decl *CopyDecl(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx, 109 clang::Decl *decl); 110 111 lldb::opaque_compiler_type_t DeportType(clang::ASTContext *dst_ctx, 112 clang::ASTContext *src_ctx, 113 lldb::opaque_compiler_type_t type); 114 115 clang::Decl *DeportDecl(clang::ASTContext *dst_ctx, 116 clang::ASTContext *src_ctx, clang::Decl *decl); 117 118 void InsertRecordDecl(clang::RecordDecl *decl, const LayoutInfo &layout); 119 120 bool LayoutRecordType( 121 const clang::RecordDecl *record_decl, uint64_t &bit_size, 122 uint64_t &alignment, 123 llvm::DenseMap<const clang::FieldDecl *, uint64_t> &field_offsets, 124 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 125 &base_offsets, 126 llvm::DenseMap<const clang::CXXRecordDecl *, clang::CharUnits> 127 &vbase_offsets); 128 129 bool CanImport(const CompilerType &type); 130 131 bool Import(const CompilerType &type); 132 133 bool CompleteType(const CompilerType &compiler_type); 134 135 void CompleteDecl(clang::Decl *decl); 136 137 bool CompleteTagDecl(clang::TagDecl *decl); 138 139 bool CompleteTagDeclWithOrigin(clang::TagDecl *decl, clang::TagDecl *origin); 140 141 bool CompleteObjCInterfaceDecl(clang::ObjCInterfaceDecl *interface_decl); 142 143 bool CompleteAndFetchChildren(clang::QualType type); 144 145 bool RequireCompleteType(clang::QualType type); 146 147 bool ResolveDeclOrigin(const clang::Decl *decl, clang::Decl **original_decl, 148 clang::ASTContext **original_ctx) { 149 DeclOrigin origin = GetDeclOrigin(decl); 150 151 if (original_decl) 152 *original_decl = origin.decl; 153 154 if (original_ctx) 155 *original_ctx = origin.ctx; 156 157 return origin.Valid(); 158 } 159 160 void SetDeclOrigin(const clang::Decl *decl, clang::Decl *original_decl); 161 162 ClangASTMetadata *GetDeclMetadata(const clang::Decl *decl); 163 164 // 165 // Namespace maps 166 // 167 168 typedef std::vector<std::pair<lldb::ModuleSP, CompilerDeclContext>> 169 NamespaceMap; 170 typedef std::shared_ptr<NamespaceMap> NamespaceMapSP; 171 172 void RegisterNamespaceMap(const clang::NamespaceDecl *decl, 173 NamespaceMapSP &namespace_map); 174 175 NamespaceMapSP GetNamespaceMap(const clang::NamespaceDecl *decl); 176 177 void BuildNamespaceMap(const clang::NamespaceDecl *decl); 178 179 // 180 // Completers for maps 181 // 182 183 class MapCompleter { 184 public: 185 virtual ~MapCompleter(); 186 187 virtual void CompleteNamespaceMap(NamespaceMapSP &namespace_map, 188 const ConstString &name, 189 NamespaceMapSP &parent_map) const = 0; 190 }; 191 192 void InstallMapCompleter(clang::ASTContext *dst_ctx, 193 MapCompleter &completer) { 194 ASTContextMetadataSP context_md; 195 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 196 197 if (context_md_iter == m_metadata_map.end()) { 198 context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); 199 m_metadata_map[dst_ctx] = context_md; 200 } else { 201 context_md = context_md_iter->second; 202 } 203 204 context_md->m_map_completer = &completer; 205 } 206 207 void ForgetDestination(clang::ASTContext *dst_ctx); 208 void ForgetSource(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); 209 210private: 211 struct DeclOrigin { 212 DeclOrigin() : ctx(nullptr), decl(nullptr) {} 213 214 DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl) 215 : ctx(_ctx), decl(_decl) {} 216 217 DeclOrigin(const DeclOrigin &rhs) { 218 ctx = rhs.ctx; 219 decl = rhs.decl; 220 } 221 222 void operator=(const DeclOrigin &rhs) { 223 ctx = rhs.ctx; 224 decl = rhs.decl; 225 } 226 227 bool Valid() { return (ctx != nullptr || decl != nullptr); } 228 229 clang::ASTContext *ctx; 230 clang::Decl *decl; 231 }; 232 233 typedef std::map<const clang::Decl *, DeclOrigin> OriginMap; 234 235 class Minion : public clang::ASTImporter { 236 public: 237 Minion(ClangASTImporter &master, clang::ASTContext *target_ctx, 238 clang::ASTContext *source_ctx) 239 : clang::ASTImporter(*target_ctx, master.m_file_manager, *source_ctx, 240 master.m_file_manager, true /*minimal*/), 241 m_decls_to_deport(nullptr), m_decls_already_deported(nullptr), 242 m_master(master), m_source_ctx(source_ctx) {} 243 244 // A call to "InitDeportWorkQueues" puts the minion into deport mode. 245 // In deport mode, every copied Decl that could require completion is 246 // recorded and placed into the decls_to_deport set. 247 // 248 // A call to "ExecuteDeportWorkQueues" completes all the Decls that 249 // are in decls_to_deport, adding any Decls it sees along the way that it 250 // hasn't already deported. It proceeds until decls_to_deport is empty. 251 // 252 // These calls must be paired. Leaving a minion in deport mode or trying 253 // to start deport minion with a new pair of queues will result in an 254 // assertion failure. 255 256 void 257 InitDeportWorkQueues(std::set<clang::NamedDecl *> *decls_to_deport, 258 std::set<clang::NamedDecl *> *decls_already_deported); 259 void ExecuteDeportWorkQueues(); 260 261 void ImportDefinitionTo(clang::Decl *to, clang::Decl *from); 262 263 clang::Decl *Imported(clang::Decl *from, clang::Decl *to) override; 264 265 clang::Decl *GetOriginalDecl(clang::Decl *To) override; 266 267 std::set<clang::NamedDecl *> *m_decls_to_deport; 268 std::set<clang::NamedDecl *> *m_decls_already_deported; 269 ClangASTImporter &m_master; 270 clang::ASTContext *m_source_ctx; 271 }; 272 273 typedef std::shared_ptr<Minion> MinionSP; 274 typedef std::map<clang::ASTContext *, MinionSP> MinionMap; 275 typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> 276 NamespaceMetaMap; 277 278 struct ASTContextMetadata { 279 ASTContextMetadata(clang::ASTContext *dst_ctx) 280 : m_dst_ctx(dst_ctx), m_minions(), m_origins(), m_namespace_maps(), 281 m_map_completer(nullptr) {} 282 283 clang::ASTContext *m_dst_ctx; 284 MinionMap m_minions; 285 OriginMap m_origins; 286 287 NamespaceMetaMap m_namespace_maps; 288 MapCompleter *m_map_completer; 289 }; 290 291 typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP; 292 typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> 293 ContextMetadataMap; 294 295 ContextMetadataMap m_metadata_map; 296 297 ASTContextMetadataSP GetContextMetadata(clang::ASTContext *dst_ctx) { 298 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 299 300 if (context_md_iter == m_metadata_map.end()) { 301 ASTContextMetadataSP context_md = 302 ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); 303 m_metadata_map[dst_ctx] = context_md; 304 return context_md; 305 } else { 306 return context_md_iter->second; 307 } 308 } 309 310 ASTContextMetadataSP MaybeGetContextMetadata(clang::ASTContext *dst_ctx) { 311 ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); 312 313 if (context_md_iter != m_metadata_map.end()) 314 return context_md_iter->second; 315 else 316 return ASTContextMetadataSP(); 317 } 318 319 MinionSP GetMinion(clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) { 320 ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx); 321 322 MinionMap &minions = context_md->m_minions; 323 MinionMap::iterator minion_iter = minions.find(src_ctx); 324 325 if (minion_iter == minions.end()) { 326 MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx)); 327 minions[src_ctx] = minion; 328 return minion; 329 } else { 330 return minion_iter->second; 331 } 332 } 333 334 DeclOrigin GetDeclOrigin(const clang::Decl *decl); 335 336 clang::FileManager m_file_manager; 337 typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> 338 RecordDeclToLayoutMap; 339 340 RecordDeclToLayoutMap m_record_decl_to_layout_map; 341}; 342 343} // namespace lldb_private 344 345#endif // liblldb_ClangASTImporter_h_ 346