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 ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) { 129 return ConstString(); 130 } 131 132 CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) { 133 return CompilerDeclContext(); 134 } 135 136 CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) { 137 return CompilerType(); 138 } 139 140 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; } 141 142 CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl, 143 size_t arg_idx) { 144 return CompilerType(); 145 } 146 147 std::vector<CompilerDecl> 148 TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, 149 bool ignore_imported_decls) { 150 return std::vector<CompilerDecl>(); 151 } 152 153 #pragma mark TypeSystemMap 154 155 TypeSystemMap::TypeSystemMap() 156 : m_mutex(), m_map(), m_clear_in_progress(false) {} 157 158 TypeSystemMap::~TypeSystemMap() {} 159 160 void TypeSystemMap::Clear() { 161 collection map; 162 { 163 std::lock_guard<std::mutex> guard(m_mutex); 164 map = m_map; 165 m_clear_in_progress = true; 166 } 167 std::set<TypeSystem *> visited; 168 for (auto pair : map) { 169 TypeSystem *type_system = pair.second.get(); 170 if (type_system && !visited.count(type_system)) { 171 visited.insert(type_system); 172 type_system->Finalize(); 173 } 174 } 175 map.clear(); 176 { 177 std::lock_guard<std::mutex> guard(m_mutex); 178 m_map.clear(); 179 m_clear_in_progress = false; 180 } 181 } 182 183 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) { 184 std::lock_guard<std::mutex> guard(m_mutex); 185 // Use a std::set so we only call the callback once for each unique 186 // TypeSystem instance 187 std::set<TypeSystem *> visited; 188 for (auto pair : m_map) { 189 TypeSystem *type_system = pair.second.get(); 190 if (type_system && !visited.count(type_system)) { 191 visited.insert(type_system); 192 if (!callback(type_system)) 193 break; 194 } 195 } 196 } 197 198 llvm::Expected<TypeSystem &> 199 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 200 Module *module, bool can_create) { 201 llvm::Error error = llvm::Error::success(); 202 assert(!error); // Check the success value when assertions are enabled 203 std::lock_guard<std::mutex> guard(m_mutex); 204 if (m_clear_in_progress) { 205 error = llvm::make_error<llvm::StringError>( 206 "Unable to get TypeSystem because TypeSystemMap is being cleared", 207 llvm::inconvertibleErrorCode()); 208 } else { 209 collection::iterator pos = m_map.find(language); 210 if (pos != m_map.end()) { 211 auto *type_system = pos->second.get(); 212 if (type_system) { 213 llvm::consumeError(std::move(error)); 214 return *type_system; 215 } 216 error = llvm::make_error<llvm::StringError>( 217 "TypeSystem for language " + 218 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 219 " doesn't exist", 220 llvm::inconvertibleErrorCode()); 221 return std::move(error); 222 } 223 224 for (const auto &pair : m_map) { 225 if (pair.second && pair.second->SupportsLanguage(language)) { 226 // Add a new mapping for "language" to point to an already existing 227 // TypeSystem that supports this language 228 m_map[language] = pair.second; 229 if (pair.second.get()) { 230 llvm::consumeError(std::move(error)); 231 return *pair.second.get(); 232 } 233 error = llvm::make_error<llvm::StringError>( 234 "TypeSystem for language " + 235 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 236 " doesn't exist", 237 llvm::inconvertibleErrorCode()); 238 return std::move(error); 239 } 240 } 241 242 if (!can_create) { 243 error = llvm::make_error<llvm::StringError>( 244 "Unable to find type system for language " + 245 llvm::toStringRef(Language::GetNameForLanguageType(language)), 246 llvm::inconvertibleErrorCode()); 247 } else { 248 // Cache even if we get a shared pointer that contains a null type system 249 // back 250 auto type_system_sp = TypeSystem::CreateInstance(language, module); 251 m_map[language] = type_system_sp; 252 if (type_system_sp.get()) { 253 llvm::consumeError(std::move(error)); 254 return *type_system_sp.get(); 255 } 256 error = llvm::make_error<llvm::StringError>( 257 "TypeSystem for language " + 258 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 259 " doesn't exist", 260 llvm::inconvertibleErrorCode()); 261 } 262 } 263 264 return std::move(error); 265 } 266 267 llvm::Expected<TypeSystem &> 268 TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language, 269 Target *target, bool can_create) { 270 llvm::Error error = llvm::Error::success(); 271 assert(!error); // Check the success value when assertions are enabled 272 std::lock_guard<std::mutex> guard(m_mutex); 273 if (m_clear_in_progress) { 274 error = llvm::make_error<llvm::StringError>( 275 "Unable to get TypeSystem because TypeSystemMap is being cleared", 276 llvm::inconvertibleErrorCode()); 277 } else { 278 collection::iterator pos = m_map.find(language); 279 if (pos != m_map.end()) { 280 auto *type_system = pos->second.get(); 281 if (type_system) { 282 llvm::consumeError(std::move(error)); 283 return *type_system; 284 } 285 error = llvm::make_error<llvm::StringError>( 286 "TypeSystem for language " + 287 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 288 " doesn't exist", 289 llvm::inconvertibleErrorCode()); 290 return std::move(error); 291 } 292 293 for (const auto &pair : m_map) { 294 if (pair.second && pair.second->SupportsLanguage(language)) { 295 // Add a new mapping for "language" to point to an already existing 296 // TypeSystem that supports this language 297 m_map[language] = pair.second; 298 if (pair.second.get()) { 299 llvm::consumeError(std::move(error)); 300 return *pair.second.get(); 301 } 302 error = llvm::make_error<llvm::StringError>( 303 "TypeSystem for language " + 304 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 305 " doesn't exist", 306 llvm::inconvertibleErrorCode()); 307 return std::move(error); 308 } 309 } 310 311 if (!can_create) { 312 error = llvm::make_error<llvm::StringError>( 313 "Unable to find type system for language " + 314 llvm::toStringRef(Language::GetNameForLanguageType(language)), 315 llvm::inconvertibleErrorCode()); 316 } else { 317 // Cache even if we get a shared pointer that contains a null type system 318 // back 319 auto type_system_sp = TypeSystem::CreateInstance(language, target); 320 m_map[language] = type_system_sp; 321 if (type_system_sp.get()) { 322 llvm::consumeError(std::move(error)); 323 return *type_system_sp.get(); 324 } 325 error = llvm::make_error<llvm::StringError>( 326 "TypeSystem for language " + 327 llvm::toStringRef(Language::GetNameForLanguageType(language)) + 328 " doesn't exist", 329 llvm::inconvertibleErrorCode()); 330 } 331 } 332 333 return std::move(error); 334 } 335