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