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 | idx: 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, target: nullptr); |
58 | } |
59 | |
60 | lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, |
61 | Target *target) { |
62 | return CreateInstanceHelper(language, module: 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, BaseOnly: 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(V: pair.second.get())) |
229 | continue; |
230 | visited.insert(V: 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(V: type_system)) |
261 | continue; |
262 | visited.insert(V: 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 | Fmt: "Unable to get TypeSystem because TypeSystemMap is being cleared"); |
276 | |
277 | collection::iterator pos = m_map.find(Val: 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 | S: "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 | S: "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 | S: "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 | S: "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, create_callback: 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, create_callback: 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 |
Definitions
- g_num_small_bitvector_bits
- LanguageSet
- GetSingularLanguage
- Insert
- Size
- Empty
- operator[]
- TypeSystem
- ~TypeSystem
- CreateInstanceHelper
- CreateInstance
- CreateInstance
- Verify
- IsAnonymousType
- GetArrayType
- GetLValueReferenceType
- GetRValueReferenceType
- GetAtomicType
- AddConstModifier
- AddPtrAuthModifier
- AddVolatileModifier
- AddRestrictModifier
- CreateTypedef
- GetBuiltinTypeByName
- GetTypeForFormatters
- IsTemplateType
- GetNumTemplateArguments
- GetTemplateArgumentKind
- GetTypeTemplateArgument
- GetIntegralTemplateArgument
- ShouldPrintAsOneLiner
- IsMeaninglessWithoutDynamicResolution
- GetMangledTypeName
- DeclGetMangledName
- DeclGetDeclContext
- DeclGetFunctionReturnType
- DeclGetFunctionNumArguments
- DeclGetFunctionArgumentType
- DeclGetCompilerContext
- DeclContextGetCompilerContext
- DeclContextFindDeclByName
- CreateUtilityFunction
- ReportStatistics
- GetCompilerDeclContextForType
- TypeSystemMap
- ~TypeSystemMap
- Clear
- ForEach
- GetTypeSystemForLanguage
- GetTypeSystemForLanguage
- GetTypeSystemForLanguage
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more