1 //===-- TypeSystem.cpp ------------------------------------------*- 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 //
11 //  TypeSystem.cpp
12 //  lldb
13 //
14 //  Created by Ryan Brown on 3/29/15.
15 //
16 //
17 
18 #include "lldb/Symbol/TypeSystem.h"
19 
20 #include <set>
21 
22 #include "lldb/Core/PluginManager.h"
23 #include "lldb/Symbol/CompilerType.h"
24 
25 using namespace lldb_private;
26 
27 TypeSystem::TypeSystem(LLVMCastKind kind) : m_kind(kind), m_sym_file(nullptr) {}
28 
29 TypeSystem::~TypeSystem() {}
30 
31 static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
32                                                Module *module, Target *target) {
33   uint32_t i = 0;
34   TypeSystemCreateInstance create_callback;
35   while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex(
36               i++)) != nullptr) {
37     lldb::TypeSystemSP type_system_sp =
38         create_callback(language, module, target);
39     if (type_system_sp)
40       return type_system_sp;
41   }
42 
43   return lldb::TypeSystemSP();
44 }
45 
46 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
47                                               Module *module) {
48   return CreateInstanceHelper(language, module, nullptr);
49 }
50 
51 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
52                                               Target *target) {
53   return CreateInstanceHelper(language, nullptr, target);
54 }
55 
56 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
57   return false;
58 }
59 
60 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,
61                                       uint64_t size) {
62   return CompilerType();
63 }
64 
65 CompilerType
66 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
67   return CompilerType();
68 }
69 
70 CompilerType
71 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
72   return CompilerType();
73 }
74 
75 CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
76   return CompilerType();
77 }
78 
79 CompilerType
80 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
81   return CompilerType();
82 }
83 
84 CompilerType
85 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
86   return CompilerType();
87 }
88 
89 CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,
90                                        const char *name,
91                                        const CompilerDeclContext &decl_ctx) {
92   return CompilerType();
93 }
94 
95 CompilerType TypeSystem::GetBuiltinTypeByName(const ConstString &name) {
96   return CompilerType();
97 }
98 
99 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
100   return CompilerType(this, type);
101 }
102 
103 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
104   return eLazyBoolCalculate;
105 }
106 
107 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
108   return false;
109 }
110 
111 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
112   return ConstString();
113 }
114 
115 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
116   return CompilerDeclContext();
117 }
118 
119 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
120   return CompilerType();
121 }
122 
123 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
124 
125 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
126                                                      size_t arg_idx) {
127   return CompilerType();
128 }
129 
130 std::vector<CompilerDecl>
131 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
132                                       bool ignore_imported_decls) {
133   return std::vector<CompilerDecl>();
134 }
135 
136 #pragma mark TypeSystemMap
137 
138 TypeSystemMap::TypeSystemMap()
139     : m_mutex(), m_map(), m_clear_in_progress(false) {}
140 
141 TypeSystemMap::~TypeSystemMap() {}
142 
143 void TypeSystemMap::Clear() {
144   collection map;
145   {
146     std::lock_guard<std::mutex> guard(m_mutex);
147     map = m_map;
148     m_clear_in_progress = true;
149   }
150   std::set<TypeSystem *> visited;
151   for (auto pair : map) {
152     TypeSystem *type_system = pair.second.get();
153     if (type_system && !visited.count(type_system)) {
154       visited.insert(type_system);
155       type_system->Finalize();
156     }
157   }
158   map.clear();
159   {
160     std::lock_guard<std::mutex> guard(m_mutex);
161     m_map.clear();
162     m_clear_in_progress = false;
163   }
164 }
165 
166 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) {
167   std::lock_guard<std::mutex> guard(m_mutex);
168   // Use a std::set so we only call the callback once for each unique
169   // TypeSystem instance
170   std::set<TypeSystem *> visited;
171   for (auto pair : m_map) {
172     TypeSystem *type_system = pair.second.get();
173     if (type_system && !visited.count(type_system)) {
174       visited.insert(type_system);
175       if (callback(type_system) == false)
176         break;
177     }
178   }
179 }
180 
181 TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
182                                                     Module *module,
183                                                     bool can_create) {
184   std::lock_guard<std::mutex> guard(m_mutex);
185   collection::iterator pos = m_map.find(language);
186   if (pos != m_map.end())
187     return pos->second.get();
188 
189   for (const auto &pair : m_map) {
190     if (pair.second && pair.second->SupportsLanguage(language)) {
191       // Add a new mapping for "language" to point to an already existing
192       // TypeSystem that supports this language
193       AddToMap(language, pair.second);
194       return pair.second.get();
195     }
196   }
197 
198   if (!can_create)
199     return nullptr;
200 
201   // Cache even if we get a shared pointer that contains null type system back
202   lldb::TypeSystemSP type_system_sp =
203       TypeSystem::CreateInstance(language, module);
204   AddToMap(language, type_system_sp);
205   return type_system_sp.get();
206 }
207 
208 TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
209                                                     Target *target,
210                                                     bool can_create) {
211   std::lock_guard<std::mutex> guard(m_mutex);
212   collection::iterator pos = m_map.find(language);
213   if (pos != m_map.end())
214     return pos->second.get();
215 
216   for (const auto &pair : m_map) {
217     if (pair.second && pair.second->SupportsLanguage(language)) {
218       // Add a new mapping for "language" to point to an already existing
219       // TypeSystem that supports this language
220 
221       AddToMap(language, pair.second);
222       return pair.second.get();
223     }
224   }
225 
226   if (!can_create)
227     return nullptr;
228 
229   // Cache even if we get a shared pointer that contains null type system back
230   lldb::TypeSystemSP type_system_sp;
231   if (!m_clear_in_progress)
232     type_system_sp = TypeSystem::CreateInstance(language, target);
233 
234   AddToMap(language, type_system_sp);
235   return type_system_sp.get();
236 }
237 
238 void TypeSystemMap::AddToMap(lldb::LanguageType language,
239                              lldb::TypeSystemSP const &type_system_sp) {
240   if (!m_clear_in_progress)
241     m_map[language] = type_system_sp;
242 }
243