1 //===-- TypeSystem.cpp ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 //
10 //  TypeSystem.cpp
11 //  lldb
12 //
13 //  Created by Ryan Brown on 3/29/15.
14 //
15 //
16 
17 #include "lldb/Symbol/TypeSystem.h"
18 
19 #include <set>
20 
21 #include "lldb/Core/PluginManager.h"
22 #include "lldb/Symbol/CompilerType.h"
23 
24 using namespace lldb_private;
25 using namespace lldb;
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(ConstString name) {
96   return CompilerType();
97 }
98 
99 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
100   return CompilerType(this, type);
101 }
102 
103 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) {
104   return 0;
105 }
106 
107 TemplateArgumentKind
108 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) {
109   return eTemplateArgumentKindNull;
110 }
111 
112 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
113                                                  size_t idx) {
114   return CompilerType();
115 }
116 
117 llvm::Optional<CompilerType::IntegralTemplateArgument>
118 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type,
119                                         size_t idx) {
120   return llvm::None;
121 }
122 
123 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
124   return eLazyBoolCalculate;
125 }
126 
127 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
128   return false;
129 }
130 
131 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
132   return ConstString();
133 }
134 
135 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
136   return CompilerDeclContext();
137 }
138 
139 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
140   return CompilerType();
141 }
142 
143 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
144 
145 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
146                                                      size_t arg_idx) {
147   return CompilerType();
148 }
149 
150 std::vector<CompilerDecl>
151 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
152                                       bool ignore_imported_decls) {
153   return std::vector<CompilerDecl>();
154 }
155 
156 #pragma mark TypeSystemMap
157 
158 TypeSystemMap::TypeSystemMap()
159     : m_mutex(), m_map(), m_clear_in_progress(false) {}
160 
161 TypeSystemMap::~TypeSystemMap() {}
162 
163 void TypeSystemMap::Clear() {
164   collection map;
165   {
166     std::lock_guard<std::mutex> guard(m_mutex);
167     map = m_map;
168     m_clear_in_progress = true;
169   }
170   std::set<TypeSystem *> visited;
171   for (auto pair : map) {
172     TypeSystem *type_system = pair.second.get();
173     if (type_system && !visited.count(type_system)) {
174       visited.insert(type_system);
175       type_system->Finalize();
176     }
177   }
178   map.clear();
179   {
180     std::lock_guard<std::mutex> guard(m_mutex);
181     m_map.clear();
182     m_clear_in_progress = false;
183   }
184 }
185 
186 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) {
187   std::lock_guard<std::mutex> guard(m_mutex);
188   // Use a std::set so we only call the callback once for each unique
189   // TypeSystem instance
190   std::set<TypeSystem *> visited;
191   for (auto pair : m_map) {
192     TypeSystem *type_system = pair.second.get();
193     if (type_system && !visited.count(type_system)) {
194       visited.insert(type_system);
195       if (!callback(type_system))
196         break;
197     }
198   }
199 }
200 
201 TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
202                                                     Module *module,
203                                                     bool can_create) {
204   std::lock_guard<std::mutex> guard(m_mutex);
205   collection::iterator pos = m_map.find(language);
206   if (pos != m_map.end())
207     return pos->second.get();
208 
209   for (const auto &pair : m_map) {
210     if (pair.second && pair.second->SupportsLanguage(language)) {
211       // Add a new mapping for "language" to point to an already existing
212       // TypeSystem that supports this language
213       AddToMap(language, pair.second);
214       return pair.second.get();
215     }
216   }
217 
218   if (!can_create)
219     return nullptr;
220 
221   // Cache even if we get a shared pointer that contains null type system back
222   lldb::TypeSystemSP type_system_sp =
223       TypeSystem::CreateInstance(language, module);
224   AddToMap(language, type_system_sp);
225   return type_system_sp.get();
226 }
227 
228 TypeSystem *TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
229                                                     Target *target,
230                                                     bool can_create) {
231   std::lock_guard<std::mutex> guard(m_mutex);
232   collection::iterator pos = m_map.find(language);
233   if (pos != m_map.end())
234     return pos->second.get();
235 
236   for (const auto &pair : m_map) {
237     if (pair.second && pair.second->SupportsLanguage(language)) {
238       // Add a new mapping for "language" to point to an already existing
239       // TypeSystem that supports this language
240 
241       AddToMap(language, pair.second);
242       return pair.second.get();
243     }
244   }
245 
246   if (!can_create)
247     return nullptr;
248 
249   // Cache even if we get a shared pointer that contains null type system back
250   lldb::TypeSystemSP type_system_sp;
251   if (!m_clear_in_progress)
252     type_system_sp = TypeSystem::CreateInstance(language, target);
253 
254   AddToMap(language, type_system_sp);
255   return type_system_sp.get();
256 }
257 
258 void TypeSystemMap::AddToMap(lldb::LanguageType language,
259                              lldb::TypeSystemSP const &type_system_sp) {
260   if (!m_clear_in_progress)
261     m_map[language] = type_system_sp;
262 }
263