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 <set> 16 17 using namespace lldb_private; 18 using namespace lldb; 19 20 /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the 21 /// setBitsInMask interface wants to write full bytes. 22 static const size_t g_num_small_bitvector_bits = 64 - 8; 23 static_assert(eNumLanguageTypes < g_num_small_bitvector_bits, 24 "Languages bit vector is no longer small on 64 bit systems"); 25 LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {} 26 27 llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() { 28 if (bitvector.count() == 1) 29 return (LanguageType)bitvector.find_first(); 30 return {}; 31 } 32 33 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); } 34 size_t LanguageSet::Size() const { return bitvector.count(); } 35 bool LanguageSet::Empty() const { return bitvector.none(); } 36 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; } 37 38 TypeSystem::~TypeSystem() = default; 39 40 static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, 41 Module *module, Target *target) { 42 uint32_t i = 0; 43 TypeSystemCreateInstance create_callback; 44 while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex( 45 i++)) != nullptr) { 46 lldb::TypeSystemSP type_system_sp = 47 create_callback(language, module, target); 48 if (type_system_sp) 49 return type_system_sp; 50 } 51 52 return lldb::TypeSystemSP(); 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(this, type); 119 } 120 121 size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type, 122 bool expand_pack) { 123 return 0; 124 } 125 126 TemplateArgumentKind 127 TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx, 128 bool expand_pack) { 129 return eTemplateArgumentKindNull; 130 } 131 132 CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type, 133 size_t idx, bool expand_pack) { 134 return CompilerType(); 135 } 136 137 llvm::Optional<CompilerType::IntegralTemplateArgument> 138 TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx, 139 bool expand_pack) { 140 return llvm::None; 141 } 142 143 LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) { 144 return eLazyBoolCalculate; 145 } 146 147 bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) { 148 return false; 149 } 150 151 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { 152 return ConstString(); 153 } 154 155 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { 156 return CompilerDeclContext(); 157 } 158 159 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { 160 return CompilerType(); 161 } 162 163 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } 164 165 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, 166 size_t arg_idx) { 167 return CompilerType(); 168 } 169 170 std::vector<CompilerDecl> 171 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, 172 bool ignore_imported_decls) { 173 return std::vector<CompilerDecl>(); 174 } 175 176 std::unique_ptr<UtilityFunction> 177 TypeSystem::CreateUtilityFunction(std::string text, std::string name) { 178 return {}; 179 } 180 181 #pragma mark TypeSystemMap 182 183 TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {} 184 185 TypeSystemMap::~TypeSystemMap() = default; 186 187 void TypeSystemMap::Clear() { 188 collection map; 189 { 190 std::lock_guard<std::mutex> guard(m_mutex); 191 map = m_map; 192 m_clear_in_progress = true; 193 } 194 std::set<TypeSystem *> visited; 195 for (auto pair : map) { 196 TypeSystem *type_system = pair.second.get(); 197 if (type_system && !visited.count(type_system)) { 198 visited.insert(type_system); 199 type_system->Finalize(); 200 } 201 } 202 map.clear(); 203 { 204 std::lock_guard<std::mutex> guard(m_mutex); 205 m_map.clear(); 206 m_clear_in_progress = false; 207 } 208 } 209 210 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { 211 std::lock_guard<std::mutex> guard(m_mutex); 212 // Use a std::set so we only call the callback once for each unique 213 // TypeSystem instance 214 std::set<TypeSystem *> visited; 215 for (auto pair : m_map) { 216 TypeSystem *type_system = pair.second.get(); 217 if (type_system && !visited.count(type_system)) { 218 visited.insert(type_system); 219 if (!callback(type_system)) 220 break; 221 } 222 } 223 } 224 225 llvm::Expected<TypeSystem &> TypeSystemMap::GetTypeSystemForLanguage( 226 lldb::LanguageType language, 227 llvm::Optional<CreateCallback> create_callback) { 228 std::lock_guard<std::mutex> guard(m_mutex); 229 if (m_clear_in_progress) 230 return llvm::make_error<llvm::StringError>( 231 "Unable to get TypeSystem because TypeSystemMap is being cleared", 232 llvm::inconvertibleErrorCode()); 233 234 collection::iterator pos = m_map.find(language); 235 if (pos != m_map.end()) { 236 auto *type_system = pos->second.get(); 237 if (type_system) 238 return *type_system; 239 return llvm::make_error<llvm::StringError>( 240 "TypeSystem for language " + 241 llvm::StringRef(Language::GetNameForLanguageType(language)) + 242 " doesn't exist", 243 llvm::inconvertibleErrorCode()); 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 return *pair.second.get(); 253 return llvm::make_error<llvm::StringError>( 254 "TypeSystem for language " + 255 llvm::StringRef(Language::GetNameForLanguageType(language)) + 256 " doesn't exist", 257 llvm::inconvertibleErrorCode()); 258 } 259 } 260 261 if (!create_callback) 262 return llvm::make_error<llvm::StringError>( 263 "Unable to find type system for language " + 264 llvm::StringRef(Language::GetNameForLanguageType(language)), 265 llvm::inconvertibleErrorCode()); 266 267 // Cache even if we get a shared pointer that contains a null type system 268 // back 269 TypeSystemSP type_system_sp = (*create_callback)(); 270 m_map[language] = type_system_sp; 271 if (type_system_sp.get()) 272 return *type_system_sp.get(); 273 return llvm::make_error<llvm::StringError>( 274 "TypeSystem for language " + 275 llvm::StringRef(Language::GetNameForLanguageType(language)) + 276 " doesn't exist", 277 llvm::inconvertibleErrorCode()); 278 } 279 280 llvm::Expected<TypeSystem &> 281 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 282 Module *module, bool can_create) { 283 if (can_create) { 284 return GetTypeSystemForLanguage( 285 language, llvm::Optional<CreateCallback>([language, module]() { 286 return TypeSystem::CreateInstance(language, module); 287 })); 288 } 289 return GetTypeSystemForLanguage(language); 290 } 291 292 llvm::Expected<TypeSystem &> 293 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 294 Target *target, bool can_create) { 295 if (can_create) { 296 return GetTypeSystemForLanguage( 297 language, llvm::Optional<CreateCallback>([language, target]() { 298 return TypeSystem::CreateInstance(language, target); 299 })); 300 } 301 return GetTypeSystemForLanguage(language); 302 } 303