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