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 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 uint32_t opaque_payload) { 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(weak_from_this(), type); 119 } 120 121 bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) { 122 return false; 123 } 124 125 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, 126 bool expand_pack) { 127 return 0; 128 } 129 130 TemplateArgumentKind 131 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx, 132 bool expand_pack) { 133 return eTemplateArgumentKindNull; 134 } 135 136 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, 137 size_t idx, bool expand_pack) { 138 return CompilerType(); 139 } 140 141 std::optional<CompilerType::IntegralTemplateArgument> 142 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, 143 bool expand_pack) { 144 return std::nullopt; 145 } 146 147 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { 148 return eLazyBoolCalculate; 149 } 150 151 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) { 152 return false; 153 } 154 155 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { 156 return ConstString(); 157 } 158 159 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { 160 return CompilerDeclContext(); 161 } 162 163 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { 164 return CompilerType(); 165 } 166 167 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } 168 169 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, 170 size_t arg_idx) { 171 return CompilerType(); 172 } 173 174 std::vector<CompilerDecl> 175 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, 176 bool ignore_imported_decls) { 177 return std::vector<CompilerDecl>(); 178 } 179 180 std::unique_ptr<UtilityFunction> 181 TypeSystem::CreateUtilityFunction(std::string text, std::string name) { 182 return {}; 183 } 184 185 std::optional<llvm::json::Value> TypeSystem::ReportStatistics() { 186 return std::nullopt; 187 } 188 189 #pragma mark TypeSystemMap 190 191 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {} 192 193 TypeSystemMap::~TypeSystemMap() = default; 194 195 void TypeSystemMap::Clear() { 196 collection map; 197 { 198 std::lock_guard<std::mutex> guard(m_mutex); 199 map = m_map; 200 m_clear_in_progress = true; 201 } 202 llvm::DenseSet<TypeSystem *> visited; 203 for (auto &pair : map) { 204 if (visited.count(pair.second.get())) 205 continue; 206 visited.insert(pair.second.get()); 207 if (lldb::TypeSystemSP type_system = pair.second) 208 type_system->Finalize(); 209 } 210 map.clear(); 211 { 212 std::lock_guard<std::mutex> guard(m_mutex); 213 m_map.clear(); 214 m_clear_in_progress = false; 215 } 216 } 217 218 void TypeSystemMap::ForEach( 219 std::function<bool(lldb::TypeSystemSP)> const &callback) { 220 221 // The callback may call into this function again causing 222 // us to lock m_mutex twice if we held it across the callback. 223 // Since we just care about guarding access to 'm_map', make 224 // a local copy and iterate over that instead. 225 collection map_snapshot; 226 { 227 std::lock_guard<std::mutex> guard(m_mutex); 228 map_snapshot = m_map; 229 } 230 231 // Use a std::set so we only call the callback once for each unique 232 // TypeSystem instance. 233 llvm::DenseSet<TypeSystem *> visited; 234 for (auto &pair : map_snapshot) { 235 TypeSystem *type_system = pair.second.get(); 236 if (!type_system || visited.count(type_system)) 237 continue; 238 visited.insert(type_system); 239 assert(type_system); 240 if (!callback(pair.second)) 241 break; 242 } 243 } 244 245 llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage( 246 lldb::LanguageType language, 247 std::optional<CreateCallback> create_callback) { 248 std::lock_guard<std::mutex> guard(m_mutex); 249 if (m_clear_in_progress) 250 return llvm::make_error<llvm::StringError>( 251 "Unable to get TypeSystem because TypeSystemMap is being cleared", 252 llvm::inconvertibleErrorCode()); 253 254 collection::iterator pos = m_map.find(language); 255 if (pos != m_map.end()) { 256 if (pos->second) { 257 assert(!pos->second->weak_from_this().expired()); 258 return pos->second; 259 } 260 return llvm::make_error<llvm::StringError>( 261 "TypeSystem for language " + 262 llvm::StringRef(Language::GetNameForLanguageType(language)) + 263 " doesn't exist", 264 llvm::inconvertibleErrorCode()); 265 } 266 267 for (const auto &pair : m_map) { 268 if (pair.second && pair.second->SupportsLanguage(language)) { 269 // Add a new mapping for "language" to point to an already existing 270 // TypeSystem that supports this language 271 m_map[language] = pair.second; 272 if (pair.second) 273 return pair.second; 274 return llvm::make_error<llvm::StringError>( 275 "TypeSystem for language " + 276 llvm::StringRef(Language::GetNameForLanguageType(language)) + 277 " doesn't exist", 278 llvm::inconvertibleErrorCode()); 279 } 280 } 281 282 if (!create_callback) 283 return llvm::make_error<llvm::StringError>( 284 "Unable to find type system for language " + 285 llvm::StringRef(Language::GetNameForLanguageType(language)), 286 llvm::inconvertibleErrorCode()); 287 288 // Cache even if we get a shared pointer that contains a null type system 289 // back. 290 TypeSystemSP type_system_sp = (*create_callback)(); 291 m_map[language] = type_system_sp; 292 if (type_system_sp) 293 return type_system_sp; 294 return llvm::make_error<llvm::StringError>( 295 "TypeSystem for language " + 296 llvm::StringRef(Language::GetNameForLanguageType(language)) + 297 " doesn't exist", 298 llvm::inconvertibleErrorCode()); 299 } 300 301 llvm::Expected<lldb::TypeSystemSP> 302 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 303 Module *module, bool can_create) { 304 if (can_create) { 305 return GetTypeSystemForLanguage( 306 language, std::optional<CreateCallback>([language, module]() { 307 return TypeSystem::CreateInstance(language, module); 308 })); 309 } 310 return GetTypeSystemForLanguage(language); 311 } 312 313 llvm::Expected<lldb::TypeSystemSP> 314 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 315 Target *target, bool can_create) { 316 if (can_create) { 317 return GetTypeSystemForLanguage( 318 language, std::optional<CreateCallback>([language, target]() { 319 return TypeSystem::CreateInstance(language, target); 320 })); 321 } 322 return GetTypeSystemForLanguage(language); 323 } 324