364 lines · cpp
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-exception6//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 18using namespace lldb_private;19using namespace lldb;20 21/// A 64-bit SmallBitVector is only small up to 64-7 bits, and the22/// setBitsInMask interface wants to write full bytes.23static const size_t g_num_small_bitvector_bits = 64 - 8;24static_assert(eNumLanguageTypes < g_num_small_bitvector_bits,25 "Languages bit vector is no longer small on 64 bit systems");26LanguageSet::LanguageSet() : bitvector(eNumLanguageTypes, false) {}27 28std::optional<LanguageType> LanguageSet::GetSingularLanguage() {29 if (bitvector.count() == 1)30 return (LanguageType)bitvector.find_first();31 return {};32}33 34void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }35size_t LanguageSet::Size() const { return bitvector.count(); }36bool LanguageSet::Empty() const { return bitvector.none(); }37bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }38 39TypeSystem::TypeSystem() = default;40TypeSystem::~TypeSystem() = default;41 42static TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,43 Module *module, Target *target) {44 uint32_t i = 0;45 TypeSystemCreateInstance create_callback;46 while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex(47 i++)) != nullptr) {48 if (auto type_system_sp = create_callback(language, module, target))49 return type_system_sp;50 }51 52 return {};53}54 55lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,56 Module *module) {57 return CreateInstanceHelper(language, module, nullptr);58}59 60lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,61 Target *target) {62 return CreateInstanceHelper(language, nullptr, target);63}64 65#ifndef NDEBUG66bool TypeSystem::Verify(lldb::opaque_compiler_type_t type) { return true; }67#endif68 69bool TypeSystem::IsAnonymousType(lldb::opaque_compiler_type_t type) {70 return false;71}72 73CompilerType TypeSystem::GetArrayType(lldb::opaque_compiler_type_t type,74 uint64_t size) {75 return CompilerType();76}77 78CompilerType79TypeSystem::GetLValueReferenceType(lldb::opaque_compiler_type_t type) {80 return CompilerType();81}82 83CompilerType84TypeSystem::GetRValueReferenceType(lldb::opaque_compiler_type_t type) {85 return CompilerType();86}87 88CompilerType TypeSystem::GetAtomicType(lldb::opaque_compiler_type_t type) {89 return CompilerType();90}91 92CompilerType TypeSystem::AddConstModifier(lldb::opaque_compiler_type_t type) {93 return CompilerType();94}95 96CompilerType TypeSystem::AddPtrAuthModifier(lldb::opaque_compiler_type_t type,97 uint32_t payload) {98 return CompilerType();99}100 101CompilerType102TypeSystem::AddVolatileModifier(lldb::opaque_compiler_type_t type) {103 return CompilerType();104}105 106CompilerType107TypeSystem::AddRestrictModifier(lldb::opaque_compiler_type_t type) {108 return CompilerType();109}110 111CompilerType TypeSystem::CreateTypedef(lldb::opaque_compiler_type_t type,112 const char *name,113 const CompilerDeclContext &decl_ctx,114 uint32_t opaque_payload) {115 return CompilerType();116}117 118CompilerType TypeSystem::GetBuiltinTypeByName(ConstString name) {119 return CompilerType();120}121 122CompilerType TypeSystem::GetTypeForFormatters(void *type) {123 return CompilerType(weak_from_this(), type);124}125 126bool TypeSystem::IsPromotableIntegerType(lldb::opaque_compiler_type_t type) {127 return false;128}129 130llvm::Expected<CompilerType>131TypeSystem::DoIntegralPromotion(CompilerType from,132 ExecutionContextScope *exe_scope) {133 return llvm::createStringError(134 "Integral promotion is not implemented for this TypeSystem");135}136 137bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {138 return false;139}140 141size_t TypeSystem::GetNumTemplateArguments(lldb::opaque_compiler_type_t type,142 bool expand_pack) {143 return 0;144}145 146TemplateArgumentKind147TypeSystem::GetTemplateArgumentKind(opaque_compiler_type_t type, size_t idx,148 bool expand_pack) {149 return eTemplateArgumentKindNull;150}151 152CompilerType TypeSystem::GetTypeTemplateArgument(opaque_compiler_type_t type,153 size_t idx, bool expand_pack) {154 return CompilerType();155}156 157std::optional<CompilerType::IntegralTemplateArgument>158TypeSystem::GetIntegralTemplateArgument(opaque_compiler_type_t type, size_t idx,159 bool expand_pack) {160 return std::nullopt;161}162 163LazyBool TypeSystem::ShouldPrintAsOneLiner(void *type, ValueObject *valobj) {164 return eLazyBoolCalculate;165}166 167bool TypeSystem::IsMeaninglessWithoutDynamicResolution(void *type) {168 return false;169}170 171ConstString TypeSystem::GetMangledTypeName(void *type) {172 return GetTypeName(type, false);173}174 175ConstString TypeSystem::DeclGetMangledName(void *opaque_decl) {176 return ConstString();177}178 179CompilerDeclContext TypeSystem::DeclGetDeclContext(void *opaque_decl) {180 return CompilerDeclContext();181}182 183CompilerType TypeSystem::DeclGetFunctionReturnType(void *opaque_decl) {184 return CompilerType();185}186 187size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }188 189CompilerType TypeSystem::DeclGetFunctionArgumentType(void *opaque_decl,190 size_t arg_idx) {191 return CompilerType();192}193 194std::vector<lldb_private::CompilerContext>195TypeSystem::DeclGetCompilerContext(void *opaque_decl) {196 return {};197}198 199std::vector<lldb_private::CompilerContext>200TypeSystem::DeclContextGetCompilerContext(void *opaque_decl_ctx) {201 return {};202}203 204std::vector<CompilerDecl>205TypeSystem::DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,206 bool ignore_imported_decls) {207 return std::vector<CompilerDecl>();208}209 210std::unique_ptr<UtilityFunction>211TypeSystem::CreateUtilityFunction(std::string text, std::string name) {212 return {};213}214 215std::optional<llvm::json::Value> TypeSystem::ReportStatistics() {216 return std::nullopt;217}218 219CompilerDeclContext220TypeSystem::GetCompilerDeclContextForType(const CompilerType &type) {221 return CompilerDeclContext();222}223 224#pragma mark TypeSystemMap225 226TypeSystemMap::TypeSystemMap() : m_mutex(), m_map() {}227 228TypeSystemMap::~TypeSystemMap() = default;229 230void TypeSystemMap::Clear() {231 collection map;232 {233 std::lock_guard<std::mutex> guard(m_mutex);234 map = m_map;235 m_clear_in_progress = true;236 }237 llvm::DenseSet<TypeSystem *> visited;238 for (auto &pair : map) {239 if (visited.count(pair.second.get()))240 continue;241 visited.insert(pair.second.get());242 if (lldb::TypeSystemSP type_system = pair.second)243 type_system->Finalize();244 }245 map.clear();246 {247 std::lock_guard<std::mutex> guard(m_mutex);248 m_map.clear();249 m_clear_in_progress = false;250 }251}252 253void TypeSystemMap::ForEach(254 std::function<bool(lldb::TypeSystemSP)> const &callback) {255 256 // The callback may call into this function again causing257 // us to lock m_mutex twice if we held it across the callback.258 // Since we just care about guarding access to 'm_map', make259 // a local copy and iterate over that instead.260 collection map_snapshot;261 {262 std::lock_guard<std::mutex> guard(m_mutex);263 map_snapshot = m_map;264 }265 266 // Use a std::set so we only call the callback once for each unique267 // TypeSystem instance.268 llvm::DenseSet<TypeSystem *> visited;269 for (auto &pair : map_snapshot) {270 TypeSystem *type_system = pair.second.get();271 if (!type_system || visited.count(type_system))272 continue;273 visited.insert(type_system);274 assert(type_system);275 if (!callback(pair.second))276 break;277 }278}279 280llvm::Expected<lldb::TypeSystemSP> TypeSystemMap::GetTypeSystemForLanguage(281 lldb::LanguageType language,282 std::optional<CreateCallback> create_callback) {283 std::lock_guard<std::mutex> guard(m_mutex);284 if (m_clear_in_progress)285 return llvm::createStringError(286 "Unable to get TypeSystem because TypeSystemMap is being cleared");287 288 collection::iterator pos = m_map.find(language);289 if (pos != m_map.end()) {290 if (pos->second) {291 assert(!pos->second->weak_from_this().expired());292 return pos->second;293 }294 return llvm::createStringError(295 "TypeSystem for language " +296 llvm::StringRef(Language::GetNameForLanguageType(language)) +297 " doesn't exist");298 }299 300 for (const auto &pair : m_map) {301 if (pair.second && pair.second->SupportsLanguage(language)) {302 // Add a new mapping for "language" to point to an already existing303 // TypeSystem that supports this language304 m_map[language] = pair.second;305 if (pair.second)306 return pair.second;307 return llvm::createStringError(308 "TypeSystem for language " +309 llvm::StringRef(Language::GetNameForLanguageType(language)) +310 " doesn't exist");311 }312 }313 314 if (!create_callback)315 return llvm::createStringError(316 "Unable to find type system for language " +317 llvm::StringRef(Language::GetNameForLanguageType(language)));318 // Cache even if we get a shared pointer that contains a null type system319 // back.320 TypeSystemSP type_system_sp = (*create_callback)();321 m_map[language] = type_system_sp;322 if (type_system_sp)323 return type_system_sp;324 return llvm::createStringError(325 "TypeSystem for language " +326 llvm::StringRef(Language::GetNameForLanguageType(language)) +327 " doesn't exist");328}329 330llvm::Expected<lldb::TypeSystemSP>331TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,332 Module *module, bool can_create) {333 if (can_create) {334 return GetTypeSystemForLanguage(335 language, std::optional<CreateCallback>([language, module]() {336 return TypeSystem::CreateInstance(language, module);337 }));338 }339 return GetTypeSystemForLanguage(language);340}341 342llvm::Expected<lldb::TypeSystemSP>343TypeSystemMap::GetTypeSystemForLanguage(lldb::LanguageType language,344 Target *target, bool can_create) {345 if (can_create) {346 return GetTypeSystemForLanguage(347 language, std::optional<CreateCallback>([language, target]() {348 return TypeSystem::CreateInstance(language, target);349 }));350 }351 return GetTypeSystemForLanguage(language);352}353 354bool TypeSystem::SupportsLanguageStatic(lldb::LanguageType language) {355 if (language == eLanguageTypeUnknown || language >= eNumLanguageTypes)356 return false;357 358 LanguageSet languages =359 PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();360 if (languages.Empty())361 return false;362 return languages[language];363}364