Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Symbol / TypeSystem.cpp
blob874f12573eca3f000efd835a31bca6961844fd66
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 //===----------------------------------------------------------------------===//
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"
16 #include <optional>
18 using namespace lldb_private;
19 using namespace lldb;
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();
31 return {};
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) {
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;
52 return {};
55 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
56 Module *module) {
57 return CreateInstanceHelper(language, module, nullptr);
60 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
61 Target *target) {
62 return CreateInstanceHelper(language, nullptr, target);
65 #ifndef NDEBUG
66 bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
67 #endif
69 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
70 return false;
73 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,
74 uint64_t size) {
75 return CompilerType();
78 CompilerType
79 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
80 return CompilerType();
83 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
97 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
98 return CompilerType();
101 CompilerType
102 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
103 return CompilerType();
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();
113 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {
114 return CompilerType();
117 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
118 return CompilerType(weak_from_this(), type);
121 bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {
122 return false;
125 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
126 bool expand_pack) {
127 return 0;
130 TemplateArgumentKind
131 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
132 bool expand_pack) {
133 return eTemplateArgumentKindNull;
136 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,
137 size_t idx, bool expand_pack) {
138 return CompilerType();
141 std::optional<CompilerType::IntegralTemplateArgument>
142 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
143 bool expand_pack) {
144 return std::nullopt;
147 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
148 return eLazyBoolCalculate;
151 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
152 return false;
155 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
156 return ConstString();
159 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
160 return CompilerDeclContext();
163 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
164 return CompilerType();
167 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
169 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
170 size_t arg_idx) {
171 return CompilerType();
174 std::vector<CompilerDecl>
175 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
176 bool ignore_imported_decls) {
177 return std::vector<CompilerDecl>();
180 std::unique_ptr<UtilityFunction>
181 TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
182 return {};
185 std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {
186 return std::nullopt;
189 CompilerDeclContext
190 TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {
191 return CompilerDeclContext();
194 #pragma mark TypeSystemMap
196 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
198 TypeSystemMap::~TypeSystemMap() = default;
200 void TypeSystemMap::Clear() {
201 collection map;
203 std::lock_guard<std::mutex> guard(m_mutex);
204 map = m_map;
205 m_clear_in_progress = true;
207 llvm::DenseSet<TypeSystem *> visited;
208 for (auto &pair : map) {
209 if (visited.count(pair.second.get()))
210 continue;
211 visited.insert(pair.second.get());
212 if (lldb::TypeSystemSP type_system = pair.second)
213 type_system->Finalize();
215 map.clear();
217 std::lock_guard<std::mutex> guard(m_mutex);
218 m_map.clear();
219 m_clear_in_progress = false;
223 void TypeSystemMap::ForEach(
224 std::function<bool(lldb::TypeSystemSP)> const &callback) {
226 // The callback may call into this function again causing
227 // us to lock m_mutex twice if we held it across the callback.
228 // Since we just care about guarding access to 'm_map', make
229 // a local copy and iterate over that instead.
230 collection map_snapshot;
232 std::lock_guard<std::mutex> guard(m_mutex);
233 map_snapshot = m_map;
236 // Use a std::set so we only call the callback once for each unique
237 // TypeSystem instance.
238 llvm::DenseSet<TypeSystem *> visited;
239 for (auto &pair : map_snapshot) {
240 TypeSystem *type_system = pair.second.get();
241 if (!type_system || visited.count(type_system))
242 continue;
243 visited.insert(type_system);
244 assert(type_system);
245 if (!callback(pair.second))
246 break;
250 llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage(
251 lldb::LanguageType language,
252 std::optional<CreateCallback> create_callback) {
253 std::lock_guard<std::mutex> guard(m_mutex);
254 if (m_clear_in_progress)
255 return llvm::make_error<llvm::StringError>(
256 "Unable to get TypeSystem because TypeSystemMap is being cleared",
257 llvm::inconvertibleErrorCode());
259 collection::iterator pos = m_map.find(language);
260 if (pos != m_map.end()) {
261 if (pos->second) {
262 assert(!pos->second->weak_from_this().expired());
263 return pos->second;
265 return llvm::make_error<llvm::StringError>(
266 "TypeSystem for language " +
267 llvm::StringRef(Language::GetNameForLanguageType(language)) +
268 " doesn't exist",
269 llvm::inconvertibleErrorCode());
272 for (const auto &pair : m_map) {
273 if (pair.second && pair.second->SupportsLanguage(language)) {
274 // Add a new mapping for "language" to point to an already existing
275 // TypeSystem that supports this language
276 m_map[language] = pair.second;
277 if (pair.second)
278 return pair.second;
279 return llvm::make_error<llvm::StringError>(
280 "TypeSystem for language " +
281 llvm::StringRef(Language::GetNameForLanguageType(language)) +
282 " doesn't exist",
283 llvm::inconvertibleErrorCode());
287 if (!create_callback)
288 return llvm::make_error<llvm::StringError>(
289 "Unable to find type system for language " +
290 llvm::StringRef(Language::GetNameForLanguageType(language)),
291 llvm::inconvertibleErrorCode());
293 // Cache even if we get a shared pointer that contains a null type system
294 // back.
295 TypeSystemSP type_system_sp = (*create_callback)();
296 m_map[language] = type_system_sp;
297 if (type_system_sp)
298 return type_system_sp;
299 return llvm::make_error<llvm::StringError>(
300 "TypeSystem for language " +
301 llvm::StringRef(Language::GetNameForLanguageType(language)) +
302 " doesn't exist",
303 llvm::inconvertibleErrorCode());
306 llvm::Expected<lldb::TypeSystemSP>
307 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
308 Module *module, bool can_create) {
309 if (can_create) {
310 return GetTypeSystemForLanguage(
311 language, std::optional<CreateCallback>([language, module]() {
312 return TypeSystem::CreateInstance(language, module);
313 }));
315 return GetTypeSystemForLanguage(language);
318 llvm::Expected<lldb::TypeSystemSP>
319 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,
320 Target *target, bool can_create) {
321 if (can_create) {
322 return GetTypeSystemForLanguage(
323 language, std::optional<CreateCallback>([language, target]() {
324 return TypeSystem::CreateInstance(language, target);
325 }));
327 return GetTypeSystemForLanguage(language);