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");
LanguageSet()25 LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {}
26
GetSingularLanguage()27 llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() {
28 if (bitvector.count() == 1)
29 return (LanguageType)bitvector.find_first();
30 return {};
31 }
32
Insert(LanguageType language)33 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }
Size() const34 size_t LanguageSet::Size() const { return bitvector.count(); }
Empty() const35 bool LanguageSet::Empty() const { return bitvector.none(); }
operator [](unsigned i) const36 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
37
38 TypeSystem::~TypeSystem() = default;
39
CreateInstanceHelper(lldb::LanguageType language,Module * module,Target * target)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
CreateInstance(lldb::LanguageType language,Module * module)55 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
56 Module *module) {
57 return CreateInstanceHelper(language, module, nullptr);
58 }
59
CreateInstance(lldb::LanguageType language,Target * target)60 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
61 Target *target) {
62 return CreateInstanceHelper(language, nullptr, target);
63 }
64
65 #ifndef NDEBUG
Verify(lldb::opaque_compiler_type_t type)66 bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }
67 #endif
68
IsAnonymousType(lldb::opaque_compiler_type_t type)69 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {
70 return false;
71 }
72
GetArrayType(lldb::opaque_compiler_type_t type,uint64_t size)73 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,
74 uint64_t size) {
75 return CompilerType();
76 }
77
78 CompilerType
GetLValueReferenceType(lldb::opaque_compiler_type_t type)79 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {
80 return CompilerType();
81 }
82
83 CompilerType
GetRValueReferenceType(lldb::opaque_compiler_type_t type)84 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {
85 return CompilerType();
86 }
87
GetAtomicType(lldb::opaque_compiler_type_t type)88 CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) {
89 return CompilerType();
90 }
91
AddConstModifier(lldb::opaque_compiler_type_t type)92 CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {
93 return CompilerType();
94 }
95
96 CompilerType
AddVolatileModifier(lldb::opaque_compiler_type_t type)97 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {
98 return CompilerType();
99 }
100
101 CompilerType
AddRestrictModifier(lldb::opaque_compiler_type_t type)102 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {
103 return CompilerType();
104 }
105
CreateTypedef(lldb::opaque_compiler_type_t type,const char * name,const CompilerDeclContext & decl_ctx,uint32_t opaque_payload)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
GetBuiltinTypeByName(ConstString name)113 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {
114 return CompilerType();
115 }
116
GetTypeForFormatters(void * type)117 CompilerType TypeSystem::GetTypeForFormatters(void *type) {
118 return CompilerType(this, type);
119 }
120
GetNumTemplateArguments(lldb::opaque_compiler_type_t type,bool expand_pack)121 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
122 bool expand_pack) {
123 return 0;
124 }
125
126 TemplateArgumentKind
GetTemplateArgumentKind(opaque_compiler_type_t type,size_t idx,bool expand_pack)127 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,
128 bool expand_pack) {
129 return eTemplateArgumentKindNull;
130 }
131
GetTypeTemplateArgument(opaque_compiler_type_t type,size_t idx,bool expand_pack)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>
GetIntegralTemplateArgument(opaque_compiler_type_t type,size_t idx,bool expand_pack)138 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,
139 bool expand_pack) {
140 return llvm::None;
141 }
142
ShouldPrintAsOneLiner(void * type,ValueObject * valobj)143 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {
144 return eLazyBoolCalculate;
145 }
146
IsMeaninglessWithoutDynamicResolution(void * type)147 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {
148 return false;
149 }
150
DeclGetMangledName(void * opaque_decl)151 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {
152 return ConstString();
153 }
154
DeclGetDeclContext(void * opaque_decl)155 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {
156 return CompilerDeclContext();
157 }
158
DeclGetFunctionReturnType(void * opaque_decl)159 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {
160 return CompilerType();
161 }
162
DeclGetFunctionNumArguments(void * opaque_decl)163 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
164
DeclGetFunctionArgumentType(void * opaque_decl,size_t arg_idx)165 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,
166 size_t arg_idx) {
167 return CompilerType();
168 }
169
170 std::vector<CompilerDecl>
DeclContextFindDeclByName(void * opaque_decl_ctx,ConstString name,bool ignore_imported_decls)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>
CreateUtilityFunction(std::string text,std::string name)177 TypeSystem::CreateUtilityFunction(std::string text, std::string name) {
178 return {};
179 }
180
181 #pragma mark TypeSystemMap
182
TypeSystemMap()183 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}
184
185 TypeSystemMap::~TypeSystemMap() = default;
186
Clear()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
ForEach(std::function<bool (TypeSystem *)> const & callback)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
GetTypeSystemForLanguage(lldb::LanguageType language,llvm::Optional<CreateCallback> create_callback)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 &>
GetTypeSystemForLanguage(lldb::LanguageType language,Module * module,bool can_create)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 &>
GetTypeSystemForLanguage(lldb::LanguageType language,Target * target,bool can_create)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