xref: /llvm-project/lldb/source/Symbol/TypeSystem.cpp (revision 3d84b74cb3543428c35fc39e889684497286d482)
1 //===-- TypeSystem.cpp ----------------------------------------------------===//
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 #include "lldb/Symbol/TypeSystem.h"
10 #include "lldb/Core/PluginManager.h"
11 #include "lldb/Expression/UtilityFunction.h"
12 #include "lldb/Symbol/CompilerType.h"
13 #include "lldb/Target/Language.h"
14 
15 #include "llvm/ADT/DenseSet.h"
16 #include <optional>
17 
18 using namespace lldb_private;
19 using namespace lldb;
20 
21 /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the
22 /// setBitsInMask interface wants to write full bytes.
23 static const size_t g_num_small_bitvector_bits = 64 - 8;
24 static_assert(eNumLanguageTypes < g_num_small_bitvector_bits,
25               "Languages bit vector is no longer small on 64 bit systems");
26 LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {}
27 
28 std::optional<LanguageType> LanguageSet::GetSingularLanguage() {
29   if (bitvector.count() == 1)
30     return (LanguageType)bitvector.find_first();
31   return {};
32 }
33 
34 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }
35 size_t LanguageSet::Size() const { return bitvector.count(); }
36 bool LanguageSet::Empty() const { return bitvector.none(); }
37 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
38 
39 TypeSystem::TypeSystem() = default;
40 TypeSystem::~TypeSystem() = default;
41 
42 static TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
43                                          Module *module, Target *target) {
44   uint32_t i = 0;
45   TypeSystemCreateInstance create_callback;
46   while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex(
47               i++)) != nullptr) {
48     if (auto type_system_sp = create_callback(language, module, target))
49       return type_system_sp;
50   }
51 
52   return {};
53 }
54 
55 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
56                                               Module *module) {
57   return CreateInstanceHelper(language, module, nullptr);
58 }
59 
60 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
61                                               Target *target) {
62   return CreateInstanceHelper(language, nullptr, target);
63 }
64 
65 #ifndef NDEBUG
66 bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
67 #endif
68 
69 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
70   return false;
71 }
72 
73 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,
74                                       uint64_t size) {
75   return CompilerType();
76 }
77 
78 CompilerType
79 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
80   return CompilerType();
81 }
82 
83 CompilerType
84 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
85   return CompilerType();
86 }
87 
88 CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) {
89   return CompilerType();
90 }
91 
92 CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
93   return CompilerType();
94 }
95 
96 CompilerType TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
97                                             uint32_t payload) {
98   return CompilerType();
99 }
100 
101 CompilerType
102 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
103   return CompilerType();
104 }
105 
106 CompilerType
107 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
108   return CompilerType();
109 }
110 
111 CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,
112                                        const char *name,
113                                        const CompilerDeclContext &decl_ctx,
114                                        uint32_t opaque_payload) {
115   return CompilerType();
116 }
117 
118 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {
119   return CompilerType();
120 }
121 
122 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
123   return CompilerType(weak_from_this(), type);
124 }
125 
126 bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {
127   return false;
128 }
129 
130 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
131                                            bool expand_pack) {
132   return 0;
133 }
134 
135 TemplateArgumentKind
136 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
137                                     bool expand_pack) {
138   return eTemplateArgumentKindNull;
139 }
140 
141 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
142                                                  size_t idx, bool expand_pack) {
143   return CompilerType();
144 }
145 
146 std::optional<CompilerType::IntegralTemplateArgument>
147 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
148                                         bool expand_pack) {
149   return std::nullopt;
150 }
151 
152 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
153   return eLazyBoolCalculate;
154 }
155 
156 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
157   return false;
158 }
159 
160 ConstString TypeSystem::GetMangledTypeName(void *type) {
161   return GetTypeName(type, false);
162 }
163 
164 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
165   return ConstString();
166 }
167 
168 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
169   return CompilerDeclContext();
170 }
171 
172 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
173   return CompilerType();
174 }
175 
176 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
177 
178 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
179                                                      size_t arg_idx) {
180   return CompilerType();
181 }
182 
183 std::vector<lldb_private::CompilerContext>
184 TypeSystem::DeclGetCompilerContext(void *opaque_decl) {
185   return {};
186 }
187 
188 std::vector<lldb_private::CompilerContext>
189 TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) {
190   return {};
191 }
192 
193 std::vector<CompilerDecl>
194 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
195                                       bool ignore_imported_decls) {
196   return std::vector<CompilerDecl>();
197 }
198 
199 std::unique_ptr<UtilityFunction>
200 TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
201   return {};
202 }
203 
204 std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {
205   return std::nullopt;
206 }
207 
208 CompilerDeclContext
209 TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {
210   return CompilerDeclContext();
211 }
212 
213 #pragma mark TypeSystemMap
214 
215 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
216 
217 TypeSystemMap::~TypeSystemMap() = default;
218 
219 void TypeSystemMap::Clear() {
220   collection map;
221   {
222     std::lock_guard<std::mutex> guard(m_mutex);
223     map = m_map;
224     m_clear_in_progress = true;
225   }
226   llvm::DenseSet<TypeSystem *> visited;
227   for (auto &pair : map) {
228     if (visited.count(pair.second.get()))
229       continue;
230     visited.insert(pair.second.get());
231     if (lldb::TypeSystemSP type_system = pair.second)
232       type_system->Finalize();
233   }
234   map.clear();
235   {
236     std::lock_guard<std::mutex> guard(m_mutex);
237     m_map.clear();
238     m_clear_in_progress = false;
239   }
240 }
241 
242 void TypeSystemMap::ForEach(
243     std::function<bool(lldb::TypeSystemSP)> const &callback) {
244 
245   // The callback may call into this function again causing
246   // us to lock m_mutex twice if we held it across the callback.
247   // Since we just care about guarding access to 'm_map', make
248   // a local copy and iterate over that instead.
249   collection map_snapshot;
250   {
251       std::lock_guard<std::mutex> guard(m_mutex);
252       map_snapshot = m_map;
253   }
254 
255   // Use a std::set so we only call the callback once for each unique
256   // TypeSystem instance.
257   llvm::DenseSet<TypeSystem *> visited;
258   for (auto &pair : map_snapshot) {
259     TypeSystem *type_system = pair.second.get();
260     if (!type_system || visited.count(type_system))
261       continue;
262     visited.insert(type_system);
263     assert(type_system);
264     if (!callback(pair.second))
265       break;
266   }
267 }
268 
269 llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage(
270     lldb::LanguageType language,
271     std::optional<CreateCallback> create_callback) {
272   std::lock_guard<std::mutex> guard(m_mutex);
273   if (m_clear_in_progress)
274     return llvm::createStringError(
275         "Unable to get TypeSystem because TypeSystemMap is being cleared");
276 
277   collection::iterator pos = m_map.find(language);
278   if (pos != m_map.end()) {
279     if (pos->second) {
280       assert(!pos->second->weak_from_this().expired());
281       return pos->second;
282     }
283     return llvm::createStringError(
284         "TypeSystem for language " +
285         llvm::StringRef(Language::GetNameForLanguageType(language)) +
286         " doesn't exist");
287   }
288 
289   for (const auto &pair : m_map) {
290     if (pair.second && pair.second->SupportsLanguage(language)) {
291       // Add a new mapping for "language" to point to an already existing
292       // TypeSystem that supports this language
293       m_map[language] = pair.second;
294       if (pair.second)
295         return pair.second;
296       return llvm::createStringError(
297           "TypeSystem for language " +
298           llvm::StringRef(Language::GetNameForLanguageType(language)) +
299           " doesn't exist");
300     }
301   }
302 
303   if (!create_callback)
304     return llvm::createStringError(
305         "Unable to find type system for language " +
306         llvm::StringRef(Language::GetNameForLanguageType(language)));
307   // Cache even if we get a shared pointer that contains a null type system
308   // back.
309   TypeSystemSP type_system_sp = (*create_callback)();
310   m_map[language] = type_system_sp;
311   if (type_system_sp)
312     return type_system_sp;
313   return llvm::createStringError(
314       "TypeSystem for language " +
315       llvm::StringRef(Language::GetNameForLanguageType(language)) +
316       " doesn't exist");
317 }
318 
319 llvm::Expected<lldb::TypeSystemSP>
320 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
321                                         Module *module, bool can_create) {
322   if (can_create) {
323     return GetTypeSystemForLanguage(
324         language, std::optional<CreateCallback>([language, module]() {
325           return TypeSystem::CreateInstance(language, module);
326         }));
327   }
328   return GetTypeSystemForLanguage(language);
329 }
330 
331 llvm::Expected<lldb::TypeSystemSP>
332 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
333                                         Target *target, bool can_create) {
334   if (can_create) {
335     return GetTypeSystemForLanguage(
336         language, std::optional<CreateCallback>([language, target]() {
337           return TypeSystem::CreateInstance(language, target);
338         }));
339   }
340   return GetTypeSystemForLanguage(language);
341 }
342 
343 bool TypeSystem::SupportsLanguageStatic(lldb::LanguageType language) {
344   if (language == eLanguageTypeUnknown || language >= eNumLanguageTypes)
345     return false;
346 
347   LanguageSet languages =
348       PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
349   if (languages.Empty())
350     return false;
351   return languages[language];
352 }
353