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 
30 namespace lldb_private {
31 
32 class ClangASTMetrics {
33 public:
34   static void DumpCounters(Log *log);
ClearLocalCounters()35   static void ClearLocalCounters() { local_counters = {0, 0, 0, 0, 0, 0}; }
36 
RegisterVisibleQuery()37   static void RegisterVisibleQuery() {
38     ++global_counters.m_visible_query_count;
39     ++local_counters.m_visible_query_count;
40   }
41 
RegisterLexicalQuery()42   static void RegisterLexicalQuery() {
43     ++global_counters.m_lexical_query_count;
44     ++local_counters.m_lexical_query_count;
45   }
46 
RegisterLLDBImport()47   static void RegisterLLDBImport() {
48     ++global_counters.m_lldb_import_count;
49     ++local_counters.m_lldb_import_count;
50   }
51 
RegisterClangImport()52   static void RegisterClangImport() {
53     ++global_counters.m_clang_import_count;
54     ++local_counters.m_clang_import_count;
55   }
56 
RegisterDeclCompletion()57   static void RegisterDeclCompletion() {
58     ++global_counters.m_decls_completed_count;
59     ++local_counters.m_decls_completed_count;
60   }
61 
RegisterRecordLayout()62   static void RegisterRecordLayout() {
63     ++global_counters.m_record_layout_count;
64     ++local_counters.m_record_layout_count;
65   }
66 
67 private:
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 
83 class ClangASTImporter {
84 public:
85   struct LayoutInfo {
LayoutInfoLayoutInfo86     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 
ClangASTImporter()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 
ResolveDeclOrigin(const clang::Decl * decl,clang::Decl ** original_decl,clang::ASTContext ** original_ctx)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 
InstallMapCompleter(clang::ASTContext * dst_ctx,MapCompleter & completer)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 
210 private:
211   struct DeclOrigin {
DeclOriginDeclOrigin212     DeclOrigin() : ctx(nullptr), decl(nullptr) {}
213 
DeclOriginDeclOrigin214     DeclOrigin(clang::ASTContext *_ctx, clang::Decl *_decl)
215         : ctx(_ctx), decl(_decl) {}
216 
DeclOriginDeclOrigin217     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 
ValidDeclOrigin227     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:
Minion(ClangASTImporter & master,clang::ASTContext * target_ctx,clang::ASTContext * source_ctx)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 {
ASTContextMetadataASTContextMetadata279     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 
GetContextMetadata(clang::ASTContext * dst_ctx)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 
MaybeGetContextMetadata(clang::ASTContext * dst_ctx)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 
GetMinion(clang::ASTContext * dst_ctx,clang::ASTContext * src_ctx)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