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