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