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 <set>
16 
17 using namespace lldb_private;
18 using namespace lldb;
19 
20 /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the
21 /// setBitsInMask interface wants to write full bytes.
22 static const size_t g_num_small_bitvector_bits = 64 - 8;
23 static_assert(eNumLanguageTypes < g_num_small_bitvector_bits,
24               "Languages bit vector is no longer small on 64 bit systems");
25 LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {}
26 
27 llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() {
28   if (bitvector.count() == 1)
29     return (LanguageType)bitvector.find_first();
30   return {};
31 }
32 
33 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }
34 size_t LanguageSet::Size() const { return bitvector.count(); }
35 bool LanguageSet::Empty() const { return bitvector.none(); }
36 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
37 
38 TypeSystem::~TypeSystem() = default;
39 
40 static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
41                                                Module *module, Target *target) {
42   uint32_t i = 0;
43   TypeSystemCreateInstance create_callback;
44   while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex(
45               i++)) != nullptr) {
46     lldb::TypeSystemSP type_system_sp =
47         create_callback(language, module, target);
48     if (type_system_sp)
49       return type_system_sp;
50   }
51 
52   return lldb::TypeSystemSP();
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
97 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
98   return CompilerType();
99 }
100 
101 CompilerType
102 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
103   return CompilerType();
104 }
105 
106 CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,
107                                        const char *name,
108                                        const CompilerDeclContext &decl_ctx,
109                                        uint32_t opaque_payload) {
110   return CompilerType();
111 }
112 
113 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {
114   return CompilerType();
115 }
116 
117 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
118   return CompilerType(this, type);
119 }
120 
121 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
122                                            bool expand_pack) {
123   return 0;
124 }
125 
126 TemplateArgumentKind
127 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
128                                     bool expand_pack) {
129   return eTemplateArgumentKindNull;
130 }
131 
132 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
133                                                  size_t idx, bool expand_pack) {
134   return CompilerType();
135 }
136 
137 llvm::Optional<CompilerType::IntegralTemplateArgument>
138 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
139                                         bool expand_pack) {
140   return llvm::None;
141 }
142 
143 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
144   return eLazyBoolCalculate;
145 }
146 
147 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
148   return false;
149 }
150 
151 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
152   return ConstString();
153 }
154 
155 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
156   return CompilerDeclContext();
157 }
158 
159 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
160   return CompilerType();
161 }
162 
163 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
164 
165 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
166                                                      size_t arg_idx) {
167   return CompilerType();
168 }
169 
170 std::vector<CompilerDecl>
171 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
172                                       bool ignore_imported_decls) {
173   return std::vector<CompilerDecl>();
174 }
175 
176 std::unique_ptr<UtilityFunction>
177 TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
178   return {};
179 }
180 
181 #pragma mark TypeSystemMap
182 
183 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
184 
185 TypeSystemMap::~TypeSystemMap() = default;
186 
187 void TypeSystemMap::Clear() {
188   collection map;
189   {
190     std::lock_guard<std::mutex> guard(m_mutex);
191     map = m_map;
192     m_clear_in_progress = true;
193   }
194   std::set<TypeSystem *> visited;
195   for (auto pair : map) {
196     TypeSystem *type_system = pair.second.get();
197     if (type_system && !visited.count(type_system)) {
198       visited.insert(type_system);
199       type_system->Finalize();
200     }
201   }
202   map.clear();
203   {
204     std::lock_guard<std::mutex> guard(m_mutex);
205     m_map.clear();
206     m_clear_in_progress = false;
207   }
208 }
209 
210 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) {
211   std::lock_guard<std::mutex> guard(m_mutex);
212   // Use a std::set so we only call the callback once for each unique
213   // TypeSystem instance
214   std::set<TypeSystem *> visited;
215   for (auto pair : m_map) {
216     TypeSystem *type_system = pair.second.get();
217     if (type_system && !visited.count(type_system)) {
218       visited.insert(type_system);
219       if (!callback(type_system))
220         break;
221     }
222   }
223 }
224 
225 llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage(
226     lldb::LanguageType language,
227     llvm::Optional<CreateCallback> create_callback) {
228   std::lock_guard<std::mutex> guard(m_mutex);
229   if (m_clear_in_progress)
230     return llvm::make_error<llvm::StringError>(
231         "Unable to get TypeSystem because TypeSystemMap is being cleared",
232         llvm::inconvertibleErrorCode());
233 
234   collection::iterator pos = m_map.find(language);
235   if (pos != m_map.end()) {
236     auto *type_system = pos->second.get();
237     if (type_system)
238       return *type_system;
239     return llvm::make_error<llvm::StringError>(
240         "TypeSystem for language " +
241             llvm::StringRef(Language::GetNameForLanguageType(language)) +
242             " doesn't exist",
243         llvm::inconvertibleErrorCode());
244   }
245 
246   for (const auto &pair : m_map) {
247     if (pair.second && pair.second->SupportsLanguage(language)) {
248       // Add a new mapping for "language" to point to an already existing
249       // TypeSystem that supports this language
250       m_map[language] = pair.second;
251       if (pair.second.get())
252         return *pair.second.get();
253       return llvm::make_error<llvm::StringError>(
254           "TypeSystem for language " +
255               llvm::StringRef(Language::GetNameForLanguageType(language)) +
256               " doesn't exist",
257           llvm::inconvertibleErrorCode());
258     }
259   }
260 
261   if (!create_callback)
262     return llvm::make_error<llvm::StringError>(
263         "Unable to find type system for language " +
264             llvm::StringRef(Language::GetNameForLanguageType(language)),
265         llvm::inconvertibleErrorCode());
266 
267   // Cache even if we get a shared pointer that contains a null type system
268   // back
269   TypeSystemSP type_system_sp = (*create_callback)();
270   m_map[language] = type_system_sp;
271   if (type_system_sp.get())
272     return *type_system_sp.get();
273   return llvm::make_error<llvm::StringError>(
274       "TypeSystem for language " +
275           llvm::StringRef(Language::GetNameForLanguageType(language)) +
276           " doesn't exist",
277       llvm::inconvertibleErrorCode());
278 }
279 
280 llvm::Expected<TypeSystem &>
281 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
282                                         Module *module, bool can_create) {
283   if (can_create) {
284     return GetTypeSystemForLanguage(
285         language, llvm::Optional<CreateCallback>([language, module]() {
286           return TypeSystem::CreateInstance(language, module);
287         }));
288   }
289   return GetTypeSystemForLanguage(language);
290 }
291 
292 llvm::Expected<TypeSystem &>
293 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
294                                         Target *target, bool can_create) {
295   if (can_create) {
296     return GetTypeSystemForLanguage(
297         language, llvm::Optional<CreateCallback>([language, target]() {
298           return TypeSystem::CreateInstance(language, target);
299         }));
300   }
301   return GetTypeSystemForLanguage(language);
302 }
303