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 // 10 // TypeSystem.cpp 11 // lldb 12 // 13 // Created by Ryan Brown on 3/29/15. 14 // 15 // 16 17 #include "lldb/Symbol/TypeSystem.h" 18 19 #include <set> 20 21 #include "lldb/Core/PluginManager.h" 22 #include "lldb/Symbol/CompilerType.h" 23 #include "lldb/Target/Language.h" 24 25 using namespace lldb_private; 26 using namespace lldb; 27 28 /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the 29 /// setBitsInMask interface wants to write full bytes. 30 static const size_t g_num_small_bitvector_bits = 64 - 8; 31 static_assert(eNumLanguageTypes < g_num_small_bitvector_bits, 32 "Languages bit vector is no longer small on 64 bit systems"); 33 LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, 0) {} 34 35 llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() { 36 if (bitvector.count() == 1) 37 return (LanguageType)bitvector.find_first(); 38 return {}; 39 } 40 41 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); } 42 size_t LanguageSet::Size() const { return bitvector.count(); } 43 bool LanguageSet::Empty() const { return bitvector.none(); } 44 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; } 45 46 TypeSystem::~TypeSystem() {} 47 48 static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, 49 Module *module, Target *target) { 50 uint32_t i = 0; 51 TypeSystemCreateInstance create_callback; 52 while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( 53 i++)) != nullptr) { 54 lldb::TypeSystemSP type_system_sp = 55 create_callback(language, module, target); 56 if (type_system_sp) 57 return type_system_sp; 58 } 59 60 return lldb::TypeSystemSP(); 61 } 62 63 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, 64 Module *module) { 65 return CreateInstanceHelper(language, module, nullptr); 66 } 67 68 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language, 69 Target *target) { 70 return CreateInstanceHelper(language, nullptr, target); 71 } 72 73 #ifndef NDEBUG 74 bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; } 75 #endif 76 77 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) { 78 return false; 79 } 80 81 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type, 82 uint64_t size) { 83 return CompilerType(); 84 } 85 86 CompilerType 87 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { 88 return CompilerType(); 89 } 90 91 CompilerType 92 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) { 93 return CompilerType(); 94 } 95 96 CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) { 97 return CompilerType(); 98 } 99 100 CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) { 101 return CompilerType(); 102 } 103 104 CompilerType 105 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) { 106 return CompilerType(); 107 } 108 109 CompilerType 110 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) { 111 return CompilerType(); 112 } 113 114 CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type, 115 const char *name, 116 const CompilerDeclContext &decl_ctx) { 117 return CompilerType(); 118 } 119 120 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) { 121 return CompilerType(); 122 } 123 124 CompilerType TypeSystem::GetTypeForFormatters(void *type) { 125 return CompilerType(this, type); 126 } 127 128 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { 129 return 0; 130 } 131 132 TemplateArgumentKind 133 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { 134 return eTemplateArgumentKindNull; 135 } 136 137 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, 138 size_t idx) { 139 return CompilerType(); 140 } 141 142 llvm::Optional<CompilerType::IntegralTemplateArgument> 143 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, 144 size_t idx) { 145 return llvm::None; 146 } 147 148 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { 149 return eLazyBoolCalculate; 150 } 151 152 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) { 153 return false; 154 } 155 156 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { 157 return ConstString(); 158 } 159 160 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { 161 return CompilerDeclContext(); 162 } 163 164 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { 165 return CompilerType(); 166 } 167 168 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } 169 170 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, 171 size_t arg_idx) { 172 return CompilerType(); 173 } 174 175 std::vector<CompilerDecl> 176 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, 177 bool ignore_imported_decls) { 178 return std::vector<CompilerDecl>(); 179 } 180 181 #pragma mark TypeSystemMap 182 183 TypeSystemMap::TypeSystemMap() 184 : m_mutex(), m_map(), m_clear_in_progress(false) {} 185 186 TypeSystemMap::~TypeSystemMap() {} 187 188 void TypeSystemMap::Clear() { 189 collection map; 190 { 191 std::lock_guard<std::mutex> guard(m_mutex); 192 map = m_map; 193 m_clear_in_progress = true; 194 } 195 std::set<TypeSystem *> visited; 196 for (auto pair : map) { 197 TypeSystem *type_system = pair.second.get(); 198 if (type_system && !visited.count(type_system)) { 199 visited.insert(type_system); 200 type_system->Finalize(); 201 } 202 } 203 map.clear(); 204 { 205 std::lock_guard<std::mutex> guard(m_mutex); 206 m_map.clear(); 207 m_clear_in_progress = false; 208 } 209 } 210 211 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { 212 std::lock_guard<std::mutex> guard(m_mutex); 213 // Use a std::set so we only call the callback once for each unique 214 // TypeSystem instance 215 std::set<TypeSystem *> visited; 216 for (auto pair : m_map) { 217 TypeSystem *type_system = pair.second.get(); 218 if (type_system && !visited.count(type_system)) { 219 visited.insert(type_system); 220 if (!callback(type_system)) 221 break; 222 } 223 } 224 } 225 226 llvm::Expected<TypeSystem &> 227 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 228 Module *module, bool can_create) { 229 llvm::Error error = llvm::Error::success(); 230 assert(!error); // Check the success value when assertions are enabled 231 std::lock_guard<std::mutex> guard(m_mutex); 232 if (m_clear_in_progress) { 233 error = llvm::make_error<llvm::StringError>( 234 "Unable to get TypeSystem because TypeSystemMap is being cleared", 235 llvm::inconvertibleErrorCode()); 236 } else { 237 collection::iterator pos = m_map.find(language); 238 if (pos != m_map.end()) { 239 auto *type_system = pos->second.get(); 240 if (type_system) { 241 llvm::consumeError(std::move(error)); 242 return *type_system; 243 } 244 error = llvm::make_error<llvm::StringError>( 245 "TypeSystem for language " + 246 llvm::StringRef(Language::GetNameForLanguageType(language)) + 247 " doesn't exist", 248 llvm::inconvertibleErrorCode()); 249 return std::move(error); 250 } 251 252 for (const auto &pair : m_map) { 253 if (pair.second && pair.second->SupportsLanguage(language)) { 254 // Add a new mapping for "language" to point to an already existing 255 // TypeSystem that supports this language 256 m_map[language] = pair.second; 257 if (pair.second.get()) { 258 llvm::consumeError(std::move(error)); 259 return *pair.second.get(); 260 } 261 error = llvm::make_error<llvm::StringError>( 262 "TypeSystem for language " + 263 llvm::StringRef(Language::GetNameForLanguageType(language)) + 264 " doesn't exist", 265 llvm::inconvertibleErrorCode()); 266 return std::move(error); 267 } 268 } 269 270 if (!can_create) { 271 error = llvm::make_error<llvm::StringError>( 272 "Unable to find type system for language " + 273 llvm::StringRef(Language::GetNameForLanguageType(language)), 274 llvm::inconvertibleErrorCode()); 275 } else { 276 // Cache even if we get a shared pointer that contains a null type system 277 // back 278 auto type_system_sp = TypeSystem::CreateInstance(language, module); 279 m_map[language] = type_system_sp; 280 if (type_system_sp.get()) { 281 llvm::consumeError(std::move(error)); 282 return *type_system_sp.get(); 283 } 284 error = llvm::make_error<llvm::StringError>( 285 "TypeSystem for language " + 286 llvm::StringRef(Language::GetNameForLanguageType(language)) + 287 " doesn't exist", 288 llvm::inconvertibleErrorCode()); 289 } 290 } 291 292 return std::move(error); 293 } 294 295 llvm::Expected<TypeSystem &> 296 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 297 Target *target, bool can_create) { 298 llvm::Error error = llvm::Error::success(); 299 assert(!error); // Check the success value when assertions are enabled 300 std::lock_guard<std::mutex> guard(m_mutex); 301 if (m_clear_in_progress) { 302 error = llvm::make_error<llvm::StringError>( 303 "Unable to get TypeSystem because TypeSystemMap is being cleared", 304 llvm::inconvertibleErrorCode()); 305 } else { 306 collection::iterator pos = m_map.find(language); 307 if (pos != m_map.end()) { 308 auto *type_system = pos->second.get(); 309 if (type_system) { 310 llvm::consumeError(std::move(error)); 311 return *type_system; 312 } 313 error = llvm::make_error<llvm::StringError>( 314 "TypeSystem for language " + 315 llvm::StringRef(Language::GetNameForLanguageType(language)) + 316 " doesn't exist", 317 llvm::inconvertibleErrorCode()); 318 return std::move(error); 319 } 320 321 for (const auto &pair : m_map) { 322 if (pair.second && pair.second->SupportsLanguage(language)) { 323 // Add a new mapping for "language" to point to an already existing 324 // TypeSystem that supports this language 325 m_map[language] = pair.second; 326 if (pair.second.get()) { 327 llvm::consumeError(std::move(error)); 328 return *pair.second.get(); 329 } 330 error = llvm::make_error<llvm::StringError>( 331 "TypeSystem for language " + 332 llvm::StringRef(Language::GetNameForLanguageType(language)) + 333 " doesn't exist", 334 llvm::inconvertibleErrorCode()); 335 return std::move(error); 336 } 337 } 338 339 if (!can_create) { 340 error = llvm::make_error<llvm::StringError>( 341 "Unable to find type system for language " + 342 llvm::StringRef(Language::GetNameForLanguageType(language)), 343 llvm::inconvertibleErrorCode()); 344 } else { 345 // Cache even if we get a shared pointer that contains a null type system 346 // back 347 auto type_system_sp = TypeSystem::CreateInstance(language, target); 348 m_map[language] = type_system_sp; 349 if (type_system_sp.get()) { 350 llvm::consumeError(std::move(error)); 351 return *type_system_sp.get(); 352 } 353 error = llvm::make_error<llvm::StringError>( 354 "TypeSystem for language " + 355 llvm::StringRef(Language::GetNameForLanguageType(language)) + 356 " doesn't exist", 357 llvm::inconvertibleErrorCode()); 358 } 359 } 360 361 return std::move(error); 362 } 363