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