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