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