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
18using namespace lldb_private;
19using 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.
23static const size_t g_num_small_bitvector_bits = 64 - 8;
24static_assert(eNumLanguageTypes < g_num_small_bitvector_bits,
25 "Languages bit vector is no longer small on 64 bit systems");
26LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {}
27
28std::optional<LanguageType> LanguageSet::GetSingularLanguage() {
29 if (bitvector.count() == 1)
30 return (LanguageType)bitvector.find_first();
31 return {};
32}
33
34void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }
35size_t LanguageSet::Size() const { return bitvector.count(); }
36bool LanguageSet::Empty() const { return bitvector.none(); }
37bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
38
39TypeSystem::TypeSystem() = default;
40TypeSystem::~TypeSystem() = default;
41
42static 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
55lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
56 Module *module) {
57 return CreateInstanceHelper(language, module, target: nullptr);
58}
59
60lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
61 Target *target) {
62 return CreateInstanceHelper(language, module: nullptr, target);
63}
64
65#ifndef NDEBUG
66bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
67#endif
68
69bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
70 return false;
71}
72
73CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,
74 uint64_t size) {
75 return CompilerType();
76}
77
78CompilerType
79TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
80 return CompilerType();
81}
82
83CompilerType
84TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
85 return CompilerType();
86}
87
88CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) {
89 return CompilerType();
90}
91
92CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
93 return CompilerType();
94}
95
96CompilerType TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,
97 uint32_t payload) {
98 return CompilerType();
99}
100
101CompilerType
102TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
103 return CompilerType();
104}
105
106CompilerType
107TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
108 return CompilerType();
109}
110
111CompilerType 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
118CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {
119 return CompilerType();
120}
121
122CompilerType TypeSystem::GetTypeForFormatters(void *type) {
123 return CompilerType(weak_from_this(), type);
124}
125
126bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {
127 return false;
128}
129
130size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
131 bool expand_pack) {
132 return 0;
133}
134
135TemplateArgumentKind
136TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
137 bool expand_pack) {
138 return eTemplateArgumentKindNull;
139}
140
141CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
142 size_t idx, bool expand_pack) {
143 return CompilerType();
144}
145
146std::optional<CompilerType::IntegralTemplateArgument>
147TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
148 bool expand_pack) {
149 return std::nullopt;
150}
151
152LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
153 return eLazyBoolCalculate;
154}
155
156bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
157 return false;
158}
159
160ConstString TypeSystem::GetMangledTypeName(void *type) {
161 return GetTypeName(type, BaseOnly: false);
162}
163
164ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
165 return ConstString();
166}
167
168CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
169 return CompilerDeclContext();
170}
171
172CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
173 return CompilerType();
174}
175
176size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
177
178CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
179 size_t arg_idx) {
180 return CompilerType();
181}
182
183std::vector<lldb_private::CompilerContext>
184TypeSystem::DeclGetCompilerContext(void *opaque_decl) {
185 return {};
186}
187
188std::vector<lldb_private::CompilerContext>
189TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) {
190 return {};
191}
192
193std::vector<CompilerDecl>
194TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
195 bool ignore_imported_decls) {
196 return std::vector<CompilerDecl>();
197}
198
199std::unique_ptr<UtilityFunction>
200TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
201 return {};
202}
203
204std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {
205 return std::nullopt;
206}
207
208CompilerDeclContext
209TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {
210 return CompilerDeclContext();
211}
212
213#pragma mark TypeSystemMap
214
215TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
216
217TypeSystemMap::~TypeSystemMap() = default;
218
219void 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
242void 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
269llvm::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
319llvm::Expected<lldb::TypeSystemSP>
320TypeSystemMap::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
331llvm::Expected<lldb::TypeSystemSP>
332TypeSystemMap::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
343bool 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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of lldb/source/Symbol/TypeSystem.cpp