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