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