1 //===-- TypeSystem.cpp ------------------------------------------*- C++ -*-===// 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 bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) { 74 return false; 75 } 76 77 CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type, 78 uint64_t size) { 79 return CompilerType(); 80 } 81 82 CompilerType 83 TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) { 84 return CompilerType(); 85 } 86 87 CompilerType 88 TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) { 89 return CompilerType(); 90 } 91 92 CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) { 93 return CompilerType(); 94 } 95 96 CompilerType 97 TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) { 98 return CompilerType(); 99 } 100 101 CompilerType 102 TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) { 103 return CompilerType(); 104 } 105 106 CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type, 107 const char *name, 108 const CompilerDeclContext &decl_ctx) { 109 return CompilerType(); 110 } 111 112 CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) { 113 return CompilerType(); 114 } 115 116 CompilerType TypeSystem::GetTypeForFormatters(void *type) { 117 return CompilerType(this, type); 118 } 119 120 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type) { 121 return 0; 122 } 123 124 TemplateArgumentKind 125 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx) { 126 return eTemplateArgumentKindNull; 127 } 128 129 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, 130 size_t idx) { 131 return CompilerType(); 132 } 133 134 llvm::Optional<CompilerType::IntegralTemplateArgument> 135 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, 136 size_t idx) { 137 return llvm::None; 138 } 139 140 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { 141 return eLazyBoolCalculate; 142 } 143 144 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) { 145 return false; 146 } 147 148 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { 149 return ConstString(); 150 } 151 152 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { 153 return CompilerDeclContext(); 154 } 155 156 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { 157 return CompilerType(); 158 } 159 160 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } 161 162 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, 163 size_t arg_idx) { 164 return CompilerType(); 165 } 166 167 std::vector<CompilerDecl> 168 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, 169 bool ignore_imported_decls) { 170 return std::vector<CompilerDecl>(); 171 } 172 173 #pragma mark TypeSystemMap 174 175 TypeSystemMap::TypeSystemMap() 176 : m_mutex(), m_map(), m_clear_in_progress(false) {} 177 178 TypeSystemMap::~TypeSystemMap() {} 179 180 void TypeSystemMap::Clear() { 181 collection map; 182 { 183 std::lock_guard<std::mutex> guard(m_mutex); 184 map = m_map; 185 m_clear_in_progress = true; 186 } 187 std::set<TypeSystem *> visited; 188 for (auto pair : map) { 189 TypeSystem *type_system = pair.second.get(); 190 if (type_system && !visited.count(type_system)) { 191 visited.insert(type_system); 192 type_system->Finalize(); 193 } 194 } 195 map.clear(); 196 { 197 std::lock_guard<std::mutex> guard(m_mutex); 198 m_map.clear(); 199 m_clear_in_progress = false; 200 } 201 } 202 203 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { 204 std::lock_guard<std::mutex> guard(m_mutex); 205 // Use a std::set so we only call the callback once for each unique 206 // TypeSystem instance 207 std::set<TypeSystem *> visited; 208 for (auto pair : m_map) { 209 TypeSystem *type_system = pair.second.get(); 210 if (type_system && !visited.count(type_system)) { 211 visited.insert(type_system); 212 if (!callback(type_system)) 213 break; 214 } 215 } 216 } 217 218 llvm::Expected<TypeSystem &> 219 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 220 Module *module, bool can_create) { 221 llvm::Error error = llvm::Error::success(); 222 assert(!error); // Check the success value when assertions are enabled 223 std::lock_guard<std::mutex> guard(m_mutex); 224 if (m_clear_in_progress) { 225 error = llvm::make_error<llvm::StringError>( 226 "Unable to get TypeSystem because TypeSystemMap is being cleared", 227 llvm::inconvertibleErrorCode()); 228 } else { 229 collection::iterator pos = m_map.find(language); 230 if (pos != m_map.end()) { 231 auto *type_system = pos->second.get(); 232 if (type_system) { 233 llvm::consumeError(std::move(error)); 234 return *type_system; 235 } 236 error = llvm::make_error<llvm::StringError>( 237 "TypeSystem for language " + 238 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 239 " doesn't exist", 240 llvm::inconvertibleErrorCode()); 241 return std::move(error); 242 } 243 244 for (const auto &pair : m_map) { 245 if (pair.second && pair.second->SupportsLanguage(language)) { 246 // Add a new mapping for "language" to point to an already existing 247 // TypeSystem that supports this language 248 m_map[language] = pair.second; 249 if (pair.second.get()) { 250 llvm::consumeError(std::move(error)); 251 return *pair.second.get(); 252 } 253 error = llvm::make_error<llvm::StringError>( 254 "TypeSystem for language " + 255 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 256 " doesn't exist", 257 llvm::inconvertibleErrorCode()); 258 return std::move(error); 259 } 260 } 261 262 if (!can_create) { 263 error = llvm::make_error<llvm::StringError>( 264 "Unable to find type system for language " + 265 llvm::toStringRef(Language::GetNameForLanguageType(language)), 266 llvm::inconvertibleErrorCode()); 267 } else { 268 // Cache even if we get a shared pointer that contains a null type system 269 // back 270 auto type_system_sp = TypeSystem::CreateInstance(language, module); 271 m_map[language] = type_system_sp; 272 if (type_system_sp.get()) { 273 llvm::consumeError(std::move(error)); 274 return *type_system_sp.get(); 275 } 276 error = llvm::make_error<llvm::StringError>( 277 "TypeSystem for language " + 278 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 279 " doesn't exist", 280 llvm::inconvertibleErrorCode()); 281 } 282 } 283 284 return std::move(error); 285 } 286 287 llvm::Expected<TypeSystem &> 288 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 289 Target *target, bool can_create) { 290 llvm::Error error = llvm::Error::success(); 291 assert(!error); // Check the success value when assertions are enabled 292 std::lock_guard<std::mutex> guard(m_mutex); 293 if (m_clear_in_progress) { 294 error = llvm::make_error<llvm::StringError>( 295 "Unable to get TypeSystem because TypeSystemMap is being cleared", 296 llvm::inconvertibleErrorCode()); 297 } else { 298 collection::iterator pos = m_map.find(language); 299 if (pos != m_map.end()) { 300 auto *type_system = pos->second.get(); 301 if (type_system) { 302 llvm::consumeError(std::move(error)); 303 return *type_system; 304 } 305 error = llvm::make_error<llvm::StringError>( 306 "TypeSystem for language " + 307 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 308 " doesn't exist", 309 llvm::inconvertibleErrorCode()); 310 return std::move(error); 311 } 312 313 for (const auto &pair : m_map) { 314 if (pair.second && pair.second->SupportsLanguage(language)) { 315 // Add a new mapping for "language" to point to an already existing 316 // TypeSystem that supports this language 317 m_map[language] = pair.second; 318 if (pair.second.get()) { 319 llvm::consumeError(std::move(error)); 320 return *pair.second.get(); 321 } 322 error = llvm::make_error<llvm::StringError>( 323 "TypeSystem for language " + 324 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 325 " doesn't exist", 326 llvm::inconvertibleErrorCode()); 327 return std::move(error); 328 } 329 } 330 331 if (!can_create) { 332 error = llvm::make_error<llvm::StringError>( 333 "Unable to find type system for language " + 334 llvm::toStringRef(Language::GetNameForLanguageType(language)), 335 llvm::inconvertibleErrorCode()); 336 } else { 337 // Cache even if we get a shared pointer that contains a null type system 338 // back 339 auto type_system_sp = TypeSystem::CreateInstance(language, target); 340 m_map[language] = type_system_sp; 341 if (type_system_sp.get()) { 342 llvm::consumeError(std::move(error)); 343 return *type_system_sp.get(); 344 } 345 error = llvm::make_error<llvm::StringError>( 346 "TypeSystem for language " + 347 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 348 " doesn't exist", 349 llvm::inconvertibleErrorCode()); 350 } 351 } 352 353 return std::move(error); 354 } 355