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