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