1 //===-- TypeSystem.cpp ----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
15 #include "llvm/ADT/DenseSet.h"
18 using namespace lldb_private
;
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) {}
28 std::optional
<LanguageType
> LanguageSet::GetSingularLanguage() {
29 if (bitvector
.count() == 1)
30 return (LanguageType
)bitvector
.find_first();
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
]; }
39 TypeSystem::TypeSystem() = default;
40 TypeSystem::~TypeSystem() = default;
42 static TypeSystemSP
CreateInstanceHelper(lldb::LanguageType language
,
43 Module
*module
, Target
*target
) {
45 TypeSystemCreateInstance create_callback
;
46 while ((create_callback
= PluginManager::GetTypeSystemCreateCallbackAtIndex(
48 if (auto type_system_sp
= create_callback(language
, module
, target
))
49 return type_system_sp
;
55 lldb::TypeSystemSP
TypeSystem::CreateInstance(lldb::LanguageType language
,
57 return CreateInstanceHelper(language
, module
, nullptr);
60 lldb::TypeSystemSP
TypeSystem::CreateInstance(lldb::LanguageType language
,
62 return CreateInstanceHelper(language
, nullptr, target
);
66 bool TypeSystem::Verify(lldb::opaque_compiler_type_t type
) { return true; }
69 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type
) {
73 CompilerType
TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type
,
75 return CompilerType();
79 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type
) {
80 return CompilerType();
84 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type
) {
85 return CompilerType();
88 CompilerType
TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type
) {
89 return CompilerType();
92 CompilerType
TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type
) {
93 return CompilerType();
96 CompilerType
TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type
,
98 return CompilerType();
102 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type
) {
103 return CompilerType();
107 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type
) {
108 return CompilerType();
111 CompilerType
TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type
,
113 const CompilerDeclContext
&decl_ctx
,
114 uint32_t opaque_payload
) {
115 return CompilerType();
118 CompilerType
TypeSystem::GetBuiltinTypeByName(ConstString name
) {
119 return CompilerType();
122 CompilerType
TypeSystem::GetTypeForFormatters(void *type
) {
123 return CompilerType(weak_from_this(), type
);
126 bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type
) {
130 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type
,
136 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type
, size_t idx
,
138 return eTemplateArgumentKindNull
;
141 CompilerType
TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type
,
142 size_t idx
, bool expand_pack
) {
143 return CompilerType();
146 std::optional
<CompilerType::IntegralTemplateArgument
>
147 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type
, size_t idx
,
152 LazyBool
TypeSystem::ShouldPrintAsOneLiner(void *type
, ValueObject
*valobj
) {
153 return eLazyBoolCalculate
;
156 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type
) {
160 ConstString
TypeSystem::GetMangledTypeName(void *type
) {
161 return GetTypeName(type
, false);
164 ConstString
TypeSystem::DeclGetMangledName(void *opaque_decl
) {
165 return ConstString();
168 CompilerDeclContext
TypeSystem::DeclGetDeclContext(void *opaque_decl
) {
169 return CompilerDeclContext();
172 CompilerType
TypeSystem::DeclGetFunctionReturnType(void *opaque_decl
) {
173 return CompilerType();
176 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl
) { return 0; }
178 CompilerType
TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl
,
180 return CompilerType();
183 std::vector
<lldb_private::CompilerContext
>
184 TypeSystem::DeclGetCompilerContext(void *opaque_decl
) {
188 std::vector
<lldb_private::CompilerContext
>
189 TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx
) {
193 std::vector
<CompilerDecl
>
194 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx
, ConstString name
,
195 bool ignore_imported_decls
) {
196 return std::vector
<CompilerDecl
>();
199 std::unique_ptr
<UtilityFunction
>
200 TypeSystem::CreateUtilityFunction(std::string text
, std::string name
) {
204 std::optional
<llvm::json::Value
> TypeSystem::ReportStatistics() {
209 TypeSystem::GetCompilerDeclContextForType(const CompilerType
&type
) {
210 return CompilerDeclContext();
213 #pragma mark TypeSystemMap
215 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
217 TypeSystemMap::~TypeSystemMap() = default;
219 void TypeSystemMap::Clear() {
222 std::lock_guard
<std::mutex
> guard(m_mutex
);
224 m_clear_in_progress
= true;
226 llvm::DenseSet
<TypeSystem
*> visited
;
227 for (auto &pair
: map
) {
228 if (visited
.count(pair
.second
.get()))
230 visited
.insert(pair
.second
.get());
231 if (lldb::TypeSystemSP type_system
= pair
.second
)
232 type_system
->Finalize();
236 std::lock_guard
<std::mutex
> guard(m_mutex
);
238 m_clear_in_progress
= false;
242 void TypeSystemMap::ForEach(
243 std::function
<bool(lldb::TypeSystemSP
)> const &callback
) {
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
;
251 std::lock_guard
<std::mutex
> guard(m_mutex
);
252 map_snapshot
= m_map
;
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
))
262 visited
.insert(type_system
);
264 if (!callback(pair
.second
))
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");
277 collection::iterator pos
= m_map
.find(language
);
278 if (pos
!= m_map
.end()) {
280 assert(!pos
->second
->weak_from_this().expired());
283 return llvm::createStringError(
284 "TypeSystem for language " +
285 llvm::StringRef(Language::GetNameForLanguageType(language
)) +
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
;
296 return llvm::createStringError(
297 "TypeSystem for language " +
298 llvm::StringRef(Language::GetNameForLanguageType(language
)) +
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
309 TypeSystemSP type_system_sp
= (*create_callback
)();
310 m_map
[language
] = type_system_sp
;
312 return type_system_sp
;
313 return llvm::createStringError(
314 "TypeSystem for language " +
315 llvm::StringRef(Language::GetNameForLanguageType(language
)) +
319 llvm::Expected
<lldb::TypeSystemSP
>
320 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language
,
321 Module
*module
, bool can_create
) {
323 return GetTypeSystemForLanguage(
324 language
, std::optional
<CreateCallback
>([language
, module
]() {
325 return TypeSystem::CreateInstance(language
, module
);
328 return GetTypeSystemForLanguage(language
);
331 llvm::Expected
<lldb::TypeSystemSP
>
332 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language
,
333 Target
*target
, bool can_create
) {
335 return GetTypeSystemForLanguage(
336 language
, std::optional
<CreateCallback
>([language
, target
]() {
337 return TypeSystem::CreateInstance(language
, target
);
340 return GetTypeSystemForLanguage(language
);
343 bool TypeSystem::SupportsLanguageStatic(lldb::LanguageType language
) {
344 if (language
== eLanguageTypeUnknown
|| language
>= eNumLanguageTypes
)
347 LanguageSet languages
=
348 PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
349 if (languages
.Empty())
351 return languages
[language
];