Path: blob/main/contrib/llvm-project/lldb/source/Target/Language.cpp
39587 views
//===-- Language.cpp ------------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <functional>9#include <map>10#include <mutex>1112#include "lldb/Target/Language.h"1314#include "lldb/Core/PluginManager.h"15#include "lldb/Interpreter/OptionValueProperties.h"16#include "lldb/Symbol/SymbolFile.h"17#include "lldb/Symbol/TypeList.h"18#include "lldb/Target/Target.h"19#include "lldb/Utility/Stream.h"2021#include "llvm/BinaryFormat/Dwarf.h"22#include "llvm/Support/Threading.h"2324using namespace lldb;25using namespace lldb_private;26using namespace lldb_private::formatters;2728typedef std::unique_ptr<Language> LanguageUP;29typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;3031#define LLDB_PROPERTIES_language32#include "TargetProperties.inc"3334enum {35#define LLDB_PROPERTIES_language36#include "TargetPropertiesEnum.inc"37};3839LanguageProperties &Language::GetGlobalLanguageProperties() {40static LanguageProperties g_settings;41return g_settings;42}4344llvm::StringRef LanguageProperties::GetSettingName() {45static constexpr llvm::StringLiteral g_setting_name("language");46return g_setting_name;47}4849LanguageProperties::LanguageProperties() {50m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());51m_collection_sp->Initialize(g_language_properties);52}5354bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {55const uint32_t idx = ePropertyEnableFilterForLineBreakpoints;56return GetPropertyAtIndexAs<bool>(57idx, g_language_properties[idx].default_uint_value != 0);58}5960static LanguagesMap &GetLanguagesMap() {61static LanguagesMap *g_map = nullptr;62static llvm::once_flag g_initialize;6364llvm::call_once(g_initialize, [] {65g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global66// destructor chain67});6869return *g_map;70}71static std::mutex &GetLanguagesMutex() {72static std::mutex *g_mutex = nullptr;73static llvm::once_flag g_initialize;7475llvm::call_once(g_initialize, [] {76g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global77// destructor chain78});7980return *g_mutex;81}8283Language *Language::FindPlugin(lldb::LanguageType language) {84std::lock_guard<std::mutex> guard(GetLanguagesMutex());85LanguagesMap &map(GetLanguagesMap());86auto iter = map.find(language), end = map.end();87if (iter != end)88return iter->second.get();8990Language *language_ptr = nullptr;91LanguageCreateInstance create_callback;9293for (uint32_t idx = 0;94(create_callback =95PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;96++idx) {97language_ptr = create_callback(language);9899if (language_ptr) {100map[language] = std::unique_ptr<Language>(language_ptr);101return language_ptr;102}103}104105return nullptr;106}107108Language *Language::FindPlugin(llvm::StringRef file_path) {109Language *result = nullptr;110ForEach([&result, file_path](Language *language) {111if (language->IsSourceFile(file_path)) {112result = language;113return false;114}115return true;116});117return result;118}119120Language *Language::FindPlugin(LanguageType language,121llvm::StringRef file_path) {122Language *result = FindPlugin(language);123// Finding a language by file path is slower, we so we use this as the124// fallback.125if (!result)126result = FindPlugin(file_path);127return result;128}129130void Language::ForEach(std::function<bool(Language *)> callback) {131// If we want to iterate over all languages, we first have to complete the132// LanguagesMap.133static llvm::once_flag g_initialize;134llvm::call_once(g_initialize, [] {135for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;136++lang) {137FindPlugin(static_cast<lldb::LanguageType>(lang));138}139});140141// callback may call a method in Language that attempts to acquire the same142// lock (such as Language::ForEach or Language::FindPlugin). To avoid a143// deadlock, we do not use callback while holding the lock.144std::vector<Language *> loaded_plugins;145{146std::lock_guard<std::mutex> guard(GetLanguagesMutex());147LanguagesMap &map(GetLanguagesMap());148for (const auto &entry : map) {149if (entry.second)150loaded_plugins.push_back(entry.second.get());151}152}153154for (auto *lang : loaded_plugins) {155if (!callback(lang))156break;157}158}159160bool Language::IsTopLevelFunction(Function &function) { return false; }161162lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }163164HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() {165return {};166}167168HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() {169return {};170}171172HardcodedFormatters::HardcodedSyntheticFinder173Language::GetHardcodedSynthetics() {174return {};175}176177std::vector<FormattersMatchCandidate>178Language::GetPossibleFormattersMatches(ValueObject &valobj,179lldb::DynamicValueType use_dynamic) {180return {};181}182183struct language_name_pair {184const char *name;185LanguageType type;186};187188struct language_name_pair language_names[] = {189// To allow GetNameForLanguageType to be a simple array lookup, the first190// part of this array must follow enum LanguageType exactly.191{"unknown", eLanguageTypeUnknown},192{"c89", eLanguageTypeC89},193{"c", eLanguageTypeC},194{"ada83", eLanguageTypeAda83},195{"c++", eLanguageTypeC_plus_plus},196{"cobol74", eLanguageTypeCobol74},197{"cobol85", eLanguageTypeCobol85},198{"fortran77", eLanguageTypeFortran77},199{"fortran90", eLanguageTypeFortran90},200{"pascal83", eLanguageTypePascal83},201{"modula2", eLanguageTypeModula2},202{"java", eLanguageTypeJava},203{"c99", eLanguageTypeC99},204{"ada95", eLanguageTypeAda95},205{"fortran95", eLanguageTypeFortran95},206{"pli", eLanguageTypePLI},207{"objective-c", eLanguageTypeObjC},208{"objective-c++", eLanguageTypeObjC_plus_plus},209{"upc", eLanguageTypeUPC},210{"d", eLanguageTypeD},211{"python", eLanguageTypePython},212{"opencl", eLanguageTypeOpenCL},213{"go", eLanguageTypeGo},214{"modula3", eLanguageTypeModula3},215{"haskell", eLanguageTypeHaskell},216{"c++03", eLanguageTypeC_plus_plus_03},217{"c++11", eLanguageTypeC_plus_plus_11},218{"ocaml", eLanguageTypeOCaml},219{"rust", eLanguageTypeRust},220{"c11", eLanguageTypeC11},221{"swift", eLanguageTypeSwift},222{"julia", eLanguageTypeJulia},223{"dylan", eLanguageTypeDylan},224{"c++14", eLanguageTypeC_plus_plus_14},225{"fortran03", eLanguageTypeFortran03},226{"fortran08", eLanguageTypeFortran08},227{"renderscript", eLanguageTypeRenderScript},228{"bliss", eLanguageTypeBLISS},229{"kotlin", eLanguageTypeKotlin},230{"zig", eLanguageTypeZig},231{"crystal", eLanguageTypeCrystal},232{"<invalid language>",233static_cast<LanguageType>(2340x0029)}, // Not yet taken by any language in the DWARF spec235// and thus has no entry in LanguageType236{"c++17", eLanguageTypeC_plus_plus_17},237{"c++20", eLanguageTypeC_plus_plus_20},238{"c17", eLanguageTypeC17},239{"fortran18", eLanguageTypeFortran18},240{"ada2005", eLanguageTypeAda2005},241{"ada2012", eLanguageTypeAda2012},242{"HIP", eLanguageTypeHIP},243{"assembly", eLanguageTypeAssembly},244{"c-sharp", eLanguageTypeC_sharp},245{"mojo", eLanguageTypeMojo},246// Vendor Extensions247{"assembler", eLanguageTypeMipsAssembler},248// Now synonyms, in arbitrary order249{"objc", eLanguageTypeObjC},250{"objc++", eLanguageTypeObjC_plus_plus},251{"pascal", eLanguageTypePascal83}};252253static uint32_t num_languages =254sizeof(language_names) / sizeof(struct language_name_pair);255256LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {257for (const auto &L : language_names) {258if (string.equals_insensitive(L.name))259return static_cast<LanguageType>(L.type);260}261262return eLanguageTypeUnknown;263}264265const char *Language::GetNameForLanguageType(LanguageType language) {266if (language < num_languages)267return language_names[language].name;268else269return language_names[eLanguageTypeUnknown].name;270}271272void Language::PrintSupportedLanguagesForExpressions(Stream &s,273llvm::StringRef prefix,274llvm::StringRef suffix) {275auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions();276for (size_t idx = 0; idx < num_languages; ++idx) {277auto const &lang = language_names[idx];278if (supported[lang.type])279s << prefix << lang.name << suffix;280}281}282283void Language::PrintAllLanguages(Stream &s, const char *prefix,284const char *suffix) {285for (uint32_t i = 1; i < num_languages; i++) {286s.Printf("%s%s%s", prefix, language_names[i].name, suffix);287}288}289290void Language::ForAllLanguages(291std::function<bool(lldb::LanguageType)> callback) {292for (uint32_t i = 1; i < num_languages; i++) {293if (!callback(language_names[i].type))294break;295}296}297298bool Language::LanguageIsCPlusPlus(LanguageType language) {299switch (language) {300case eLanguageTypeC_plus_plus:301case eLanguageTypeC_plus_plus_03:302case eLanguageTypeC_plus_plus_11:303case eLanguageTypeC_plus_plus_14:304case eLanguageTypeC_plus_plus_17:305case eLanguageTypeC_plus_plus_20:306case eLanguageTypeObjC_plus_plus:307return true;308default:309return false;310}311}312313bool Language::LanguageIsObjC(LanguageType language) {314switch (language) {315case eLanguageTypeObjC:316case eLanguageTypeObjC_plus_plus:317return true;318default:319return false;320}321}322323bool Language::LanguageIsC(LanguageType language) {324switch (language) {325case eLanguageTypeC:326case eLanguageTypeC89:327case eLanguageTypeC99:328case eLanguageTypeC11:329return true;330default:331return false;332}333}334335bool Language::LanguageIsCFamily(LanguageType language) {336switch (language) {337case eLanguageTypeC:338case eLanguageTypeC89:339case eLanguageTypeC99:340case eLanguageTypeC11:341case eLanguageTypeC_plus_plus:342case eLanguageTypeC_plus_plus_03:343case eLanguageTypeC_plus_plus_11:344case eLanguageTypeC_plus_plus_14:345case eLanguageTypeC_plus_plus_17:346case eLanguageTypeC_plus_plus_20:347case eLanguageTypeObjC_plus_plus:348case eLanguageTypeObjC:349return true;350default:351return false;352}353}354355bool Language::LanguageIsPascal(LanguageType language) {356switch (language) {357case eLanguageTypePascal83:358return true;359default:360return false;361}362}363364LanguageType Language::GetPrimaryLanguage(LanguageType language) {365switch (language) {366case eLanguageTypeC_plus_plus:367case eLanguageTypeC_plus_plus_03:368case eLanguageTypeC_plus_plus_11:369case eLanguageTypeC_plus_plus_14:370case eLanguageTypeC_plus_plus_17:371case eLanguageTypeC_plus_plus_20:372return eLanguageTypeC_plus_plus;373case eLanguageTypeC:374case eLanguageTypeC89:375case eLanguageTypeC99:376case eLanguageTypeC11:377return eLanguageTypeC;378case eLanguageTypeObjC:379case eLanguageTypeObjC_plus_plus:380return eLanguageTypeObjC;381case eLanguageTypePascal83:382case eLanguageTypeCobol74:383case eLanguageTypeCobol85:384case eLanguageTypeFortran77:385case eLanguageTypeFortran90:386case eLanguageTypeFortran95:387case eLanguageTypeFortran03:388case eLanguageTypeFortran08:389case eLanguageTypeAda83:390case eLanguageTypeAda95:391case eLanguageTypeModula2:392case eLanguageTypeJava:393case eLanguageTypePLI:394case eLanguageTypeUPC:395case eLanguageTypeD:396case eLanguageTypePython:397case eLanguageTypeOpenCL:398case eLanguageTypeGo:399case eLanguageTypeModula3:400case eLanguageTypeHaskell:401case eLanguageTypeOCaml:402case eLanguageTypeRust:403case eLanguageTypeSwift:404case eLanguageTypeJulia:405case eLanguageTypeDylan:406case eLanguageTypeMipsAssembler:407case eLanguageTypeMojo:408case eLanguageTypeUnknown:409default:410return language;411}412}413414std::set<lldb::LanguageType> Language::GetSupportedLanguages() {415std::set<lldb::LanguageType> supported_languages;416ForEach([&](Language *lang) {417supported_languages.emplace(lang->GetLanguageType());418return true;419});420return supported_languages;421}422423LanguageSet Language::GetLanguagesSupportingTypeSystems() {424return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();425}426427LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() {428return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions();429}430431LanguageSet Language::GetLanguagesSupportingREPLs() {432return PluginManager::GetREPLAllTypeSystemSupportedLanguages();433}434435std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() {436return nullptr;437}438439const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }440441size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope,442const char *key, ResultSet &results,443bool append) {444if (!exe_scope || !exe_scope->CalculateTarget().get())445return false;446447if (!key || !key[0])448return false;449450if (!append)451results.clear();452453size_t old_size = results.size();454455if (this->Find_Impl(exe_scope, key, results))456return results.size() - old_size;457return 0;458}459460bool Language::ImageListTypeScavenger::Find_Impl(461ExecutionContextScope *exe_scope, const char *key, ResultSet &results) {462bool result = false;463464Target *target = exe_scope->CalculateTarget().get();465if (target) {466const auto &images(target->GetImages());467TypeQuery query(key);468TypeResults type_results;469images.FindTypes(nullptr, query, type_results);470for (const auto &match : type_results.GetTypeMap().Types()) {471if (match) {472CompilerType compiler_type(match->GetFullCompilerType());473compiler_type = AdjustForInclusion(compiler_type);474if (!compiler_type)475continue;476std::unique_ptr<Language::TypeScavenger::Result> scavengeresult(477new Result(compiler_type));478results.insert(std::move(scavengeresult));479result = true;480}481}482}483484return result;485}486487std::pair<llvm::StringRef, llvm::StringRef>488Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {489return std::pair<llvm::StringRef, llvm::StringRef>();490}491492bool Language::DemangledNameContainsPath(llvm::StringRef path,493ConstString demangled) const {494// The base implementation does a simple contains comparision:495if (path.empty())496return false;497return demangled.GetStringRef().contains(path);498}499500DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {501return nullptr;502}503504LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) {505return eLazyBoolCalculate;506}507508bool Language::IsNilReference(ValueObject &valobj) { return false; }509510bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }511512bool Language::GetFunctionDisplayName(const SymbolContext *sc,513const ExecutionContext *exe_ctx,514FunctionNameRepresentation representation,515Stream &s) {516return false;517}518519void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on,520Stream &s) {521GetDefaultExceptionResolverDescription(catch_on, throw_on, s);522}523524void Language::GetDefaultExceptionResolverDescription(bool catch_on,525bool throw_on,526Stream &s) {527s.Printf("Exception breakpoint (catch: %s throw: %s)",528catch_on ? "on" : "off", throw_on ? "on" : "off");529}530// Constructor531Language::Language() = default;532533// Destructor534Language::~Language() = default;535536SourceLanguage::SourceLanguage(lldb::LanguageType language_type) {537auto lname =538llvm::dwarf::toDW_LNAME((llvm::dwarf::SourceLanguage)language_type);539if (!lname)540return;541name = lname->first;542version = lname->second;543}544545lldb::LanguageType SourceLanguage::AsLanguageType() const {546if (auto lang = llvm::dwarf::toDW_LANG((llvm::dwarf::SourceLanguageName)name,547version))548return (lldb::LanguageType)*lang;549return lldb::eLanguageTypeUnknown;550}551552llvm::StringRef SourceLanguage::GetDescription() const {553LanguageType type = AsLanguageType();554if (type)555return Language::GetNameForLanguageType(type);556return llvm::dwarf::LanguageDescription(557(llvm::dwarf::SourceLanguageName)name);558}559bool SourceLanguage::IsC() const { return name == llvm::dwarf::DW_LNAME_C; }560561bool SourceLanguage::IsObjC() const {562return name == llvm::dwarf::DW_LNAME_ObjC;563}564565bool SourceLanguage::IsCPlusPlus() const {566return name == llvm::dwarf::DW_LNAME_C_plus_plus;567}568569570