brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.6 KiB · 8268d4a Raw
596 lines · cpp
1//===-- Language.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 <functional>10#include <map>11#include <mutex>12 13#include "lldb/Target/Language.h"14 15#include "lldb/Core/PluginManager.h"16#include "lldb/Interpreter/OptionValueProperties.h"17#include "lldb/Symbol/SymbolFile.h"18#include "lldb/Symbol/TypeList.h"19#include "lldb/Target/Target.h"20#include "lldb/Utility/Stream.h"21 22#include "llvm/BinaryFormat/Dwarf.h"23#include "llvm/Support/Threading.h"24 25using namespace lldb;26using namespace lldb_private;27using namespace lldb_private::formatters;28 29typedef std::unique_ptr<Language> LanguageUP;30typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;31 32#define LLDB_PROPERTIES_language33#include "TargetProperties.inc"34 35enum {36#define LLDB_PROPERTIES_language37#include "TargetPropertiesEnum.inc"38};39 40LanguageProperties &Language::GetGlobalLanguageProperties() {41  static LanguageProperties g_settings;42  return g_settings;43}44 45llvm::StringRef LanguageProperties::GetSettingName() {46  static constexpr llvm::StringLiteral g_setting_name("language");47  return g_setting_name;48}49 50LanguageProperties::LanguageProperties() {51  m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());52  m_collection_sp->Initialize(g_language_properties);53}54 55bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {56  const uint32_t idx = ePropertyEnableFilterForLineBreakpoints;57  return GetPropertyAtIndexAs<bool>(58      idx, g_language_properties[idx].default_uint_value != 0);59}60 61static LanguagesMap &GetLanguagesMap() {62  static LanguagesMap *g_map = nullptr;63  static llvm::once_flag g_initialize;64 65  llvm::call_once(g_initialize, [] {66    g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global67                                // destructor chain68  });69 70  return *g_map;71}72static std::mutex &GetLanguagesMutex() {73  static std::mutex *g_mutex = nullptr;74  static llvm::once_flag g_initialize;75 76  llvm::call_once(g_initialize, [] {77    g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global78                                // destructor chain79  });80 81  return *g_mutex;82}83 84Language *Language::FindPlugin(lldb::LanguageType language) {85  std::lock_guard<std::mutex> guard(GetLanguagesMutex());86  LanguagesMap &map(GetLanguagesMap());87  auto iter = map.find(language), end = map.end();88  if (iter != end)89    return iter->second.get();90 91  Language *language_ptr = nullptr;92  LanguageCreateInstance create_callback;93 94  for (uint32_t idx = 0;95       (create_callback =96            PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;97       ++idx) {98    language_ptr = create_callback(language);99 100    if (language_ptr) {101      map[language] = std::unique_ptr<Language>(language_ptr);102      return language_ptr;103    }104  }105 106  return nullptr;107}108 109Language *Language::FindPlugin(llvm::StringRef file_path) {110  Language *result = nullptr;111  ForEach([&result, file_path](Language *language) {112    if (language->IsSourceFile(file_path)) {113      result = language;114      return IterationAction::Stop;115    }116    return IterationAction::Continue;117  });118  return result;119}120 121Language *Language::FindPlugin(LanguageType language,122                               llvm::StringRef file_path) {123  Language *result = FindPlugin(language);124  // Finding a language by file path is slower, we so we use this as the125  // fallback.126  if (!result)127    result = FindPlugin(file_path);128  return result;129}130 131void Language::ForEach(132    llvm::function_ref<IterationAction(Language *)> callback) {133  // If we want to iterate over all languages, we first have to complete the134  // LanguagesMap.135  static llvm::once_flag g_initialize;136  llvm::call_once(g_initialize, [] {137    for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;138         ++lang) {139      FindPlugin(static_cast<lldb::LanguageType>(lang));140    }141  });142 143  // callback may call a method in Language that attempts to acquire the same144  // lock (such as Language::ForEach or Language::FindPlugin). To avoid a145  // deadlock, we do not use callback while holding the lock.146  std::vector<Language *> loaded_plugins;147  {148    std::lock_guard<std::mutex> guard(GetLanguagesMutex());149    LanguagesMap &map(GetLanguagesMap());150    for (const auto &entry : map) {151      if (entry.second)152        loaded_plugins.push_back(entry.second.get());153    }154  }155 156  for (auto *lang : loaded_plugins) {157    if (callback(lang) == IterationAction::Stop)158      break;159  }160}161 162bool Language::IsTopLevelFunction(Function &function) { return false; }163 164lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }165 166HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() {167  return {};168}169 170HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() {171  return {};172}173 174HardcodedFormatters::HardcodedSyntheticFinder175Language::GetHardcodedSynthetics() {176  return {};177}178 179std::vector<FormattersMatchCandidate>180Language::GetPossibleFormattersMatches(ValueObject &valobj,181                                       lldb::DynamicValueType use_dynamic) {182  return {};183}184 185struct language_name_pair {186  const char *name;187  LanguageType type;188};189 190struct language_name_pair language_names[] = {191    // To allow GetNameForLanguageType to be a simple array lookup, the first192    // part of this array must follow enum LanguageType exactly.193    {"unknown", eLanguageTypeUnknown},194    {"c89", eLanguageTypeC89},195    {"c", eLanguageTypeC},196    {"ada83", eLanguageTypeAda83},197    {"c++", eLanguageTypeC_plus_plus},198    {"cobol74", eLanguageTypeCobol74},199    {"cobol85", eLanguageTypeCobol85},200    {"fortran77", eLanguageTypeFortran77},201    {"fortran90", eLanguageTypeFortran90},202    {"pascal83", eLanguageTypePascal83},203    {"modula2", eLanguageTypeModula2},204    {"java", eLanguageTypeJava},205    {"c99", eLanguageTypeC99},206    {"ada95", eLanguageTypeAda95},207    {"fortran95", eLanguageTypeFortran95},208    {"pli", eLanguageTypePLI},209    {"objective-c", eLanguageTypeObjC},210    {"objective-c++", eLanguageTypeObjC_plus_plus},211    {"upc", eLanguageTypeUPC},212    {"d", eLanguageTypeD},213    {"python", eLanguageTypePython},214    {"opencl", eLanguageTypeOpenCL},215    {"go", eLanguageTypeGo},216    {"modula3", eLanguageTypeModula3},217    {"haskell", eLanguageTypeHaskell},218    {"c++03", eLanguageTypeC_plus_plus_03},219    {"c++11", eLanguageTypeC_plus_plus_11},220    {"ocaml", eLanguageTypeOCaml},221    {"rust", eLanguageTypeRust},222    {"c11", eLanguageTypeC11},223    {"swift", eLanguageTypeSwift},224    {"julia", eLanguageTypeJulia},225    {"dylan", eLanguageTypeDylan},226    {"c++14", eLanguageTypeC_plus_plus_14},227    {"fortran03", eLanguageTypeFortran03},228    {"fortran08", eLanguageTypeFortran08},229    {"renderscript", eLanguageTypeRenderScript},230    {"bliss", eLanguageTypeBLISS},231    {"kotlin", eLanguageTypeKotlin},232    {"zig", eLanguageTypeZig},233    {"crystal", eLanguageTypeCrystal},234    {"<invalid language>",235     static_cast<LanguageType>(236         0x0029)}, // Not yet taken by any language in the DWARF spec237                   // and thus has no entry in LanguageType238    {"c++17", eLanguageTypeC_plus_plus_17},239    {"c++20", eLanguageTypeC_plus_plus_20},240    {"c17", eLanguageTypeC17},241    {"fortran18", eLanguageTypeFortran18},242    {"ada2005", eLanguageTypeAda2005},243    {"ada2012", eLanguageTypeAda2012},244    {"HIP", eLanguageTypeHIP},245    {"assembly", eLanguageTypeAssembly},246    {"c-sharp", eLanguageTypeC_sharp},247    {"mojo", eLanguageTypeMojo},248    // Vendor Extensions249    {"assembler", eLanguageTypeMipsAssembler},250    // Now synonyms, in arbitrary order251    {"objc", eLanguageTypeObjC},252    {"objc++", eLanguageTypeObjC_plus_plus},253    {"pascal", eLanguageTypePascal83}};254 255static uint32_t num_languages =256    sizeof(language_names) / sizeof(struct language_name_pair);257 258LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {259  for (const auto &L : language_names) {260    if (string.equals_insensitive(L.name))261      return L.type;262  }263 264  return eLanguageTypeUnknown;265}266 267const char *Language::GetNameForLanguageType(LanguageType language) {268  if (language < num_languages)269    return language_names[language].name;270  else271    return language_names[eLanguageTypeUnknown].name;272}273 274llvm::StringRef Language::GetDisplayNameForLanguageType(LanguageType language) {275  return SourceLanguage(language).GetDescription();276}277 278void Language::PrintSupportedLanguagesForExpressions(Stream &s,279                                                     llvm::StringRef prefix,280                                                     llvm::StringRef suffix) {281  auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions();282  for (size_t idx = 0; idx < num_languages; ++idx) {283    auto const &lang = language_names[idx];284    if (supported[lang.type])285      s << prefix << lang.name << suffix;286  }287}288 289void Language::PrintAllLanguages(Stream &s, const char *prefix,290                                 const char *suffix) {291  for (uint32_t i = 1; i < num_languages; i++) {292    s.Printf("%s%s%s", prefix, language_names[i].name, suffix);293  }294}295 296void Language::ForAllLanguages(297    llvm::function_ref<IterationAction(lldb::LanguageType)> callback) {298  for (uint32_t i = 1; i < num_languages; i++) {299    if (callback(language_names[i].type) == IterationAction::Stop)300      break;301  }302}303 304bool Language::LanguageIsCPlusPlus(LanguageType language) {305  switch (language) {306  case eLanguageTypeC_plus_plus:307  case eLanguageTypeC_plus_plus_03:308  case eLanguageTypeC_plus_plus_11:309  case eLanguageTypeC_plus_plus_14:310  case eLanguageTypeC_plus_plus_17:311  case eLanguageTypeC_plus_plus_20:312  case eLanguageTypeObjC_plus_plus:313    return true;314  default:315    return false;316  }317}318 319bool Language::LanguageIsObjC(LanguageType language) {320  switch (language) {321  case eLanguageTypeObjC:322  case eLanguageTypeObjC_plus_plus:323    return true;324  default:325    return false;326  }327}328 329bool Language::LanguageIsC(LanguageType language) {330  switch (language) {331  case eLanguageTypeC:332  case eLanguageTypeC89:333  case eLanguageTypeC99:334  case eLanguageTypeC11:335    return true;336  default:337    return false;338  }339}340 341bool Language::LanguageIsCFamily(LanguageType language) {342  switch (language) {343  case eLanguageTypeC:344  case eLanguageTypeC89:345  case eLanguageTypeC99:346  case eLanguageTypeC11:347  case eLanguageTypeC_plus_plus:348  case eLanguageTypeC_plus_plus_03:349  case eLanguageTypeC_plus_plus_11:350  case eLanguageTypeC_plus_plus_14:351  case eLanguageTypeC_plus_plus_17:352  case eLanguageTypeC_plus_plus_20:353  case eLanguageTypeObjC_plus_plus:354  case eLanguageTypeObjC:355    return true;356  default:357    return false;358  }359}360 361bool Language::LanguageIsPascal(LanguageType language) {362  switch (language) {363  case eLanguageTypePascal83:364    return true;365  default:366    return false;367  }368}369 370LanguageType Language::GetPrimaryLanguage(LanguageType language) {371  switch (language) {372  case eLanguageTypeC_plus_plus:373  case eLanguageTypeC_plus_plus_03:374  case eLanguageTypeC_plus_plus_11:375  case eLanguageTypeC_plus_plus_14:376  case eLanguageTypeC_plus_plus_17:377  case eLanguageTypeC_plus_plus_20:378    return eLanguageTypeC_plus_plus;379  case eLanguageTypeC:380  case eLanguageTypeC89:381  case eLanguageTypeC99:382  case eLanguageTypeC11:383    return eLanguageTypeC;384  case eLanguageTypeObjC:385  case eLanguageTypeObjC_plus_plus:386    return eLanguageTypeObjC;387  case eLanguageTypePascal83:388  case eLanguageTypeCobol74:389  case eLanguageTypeCobol85:390  case eLanguageTypeFortran77:391  case eLanguageTypeFortran90:392  case eLanguageTypeFortran95:393  case eLanguageTypeFortran03:394  case eLanguageTypeFortran08:395  case eLanguageTypeAda83:396  case eLanguageTypeAda95:397  case eLanguageTypeModula2:398  case eLanguageTypeJava:399  case eLanguageTypePLI:400  case eLanguageTypeUPC:401  case eLanguageTypeD:402  case eLanguageTypePython:403  case eLanguageTypeOpenCL:404  case eLanguageTypeGo:405  case eLanguageTypeModula3:406  case eLanguageTypeHaskell:407  case eLanguageTypeOCaml:408  case eLanguageTypeRust:409  case eLanguageTypeSwift:410  case eLanguageTypeJulia:411  case eLanguageTypeDylan:412  case eLanguageTypeMipsAssembler:413  case eLanguageTypeMojo:414  case eLanguageTypeUnknown:415  default:416    return language;417  }418}419 420std::set<lldb::LanguageType> Language::GetSupportedLanguages() {421  std::set<lldb::LanguageType> supported_languages;422  ForEach([&](Language *lang) {423    supported_languages.emplace(lang->GetLanguageType());424    return IterationAction::Continue;425  });426  return supported_languages;427}428 429LanguageSet Language::GetLanguagesSupportingTypeSystems() {430  return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();431}432 433LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() {434  return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions();435}436 437LanguageSet Language::GetLanguagesSupportingREPLs() {438  return PluginManager::GetREPLAllTypeSystemSupportedLanguages();439}440 441std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() {442  return nullptr;443}444 445const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }446 447size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope,448                                     const char *key, ResultSet &results,449                                     bool append) {450  if (!exe_scope || !exe_scope->CalculateTarget().get())451    return false;452 453  if (!key || !key[0])454    return false;455 456  if (!append)457    results.clear();458 459  size_t old_size = results.size();460 461  if (this->Find_Impl(exe_scope, key, results))462    return results.size() - old_size;463  return 0;464}465 466bool Language::ImageListTypeScavenger::Find_Impl(467    ExecutionContextScope *exe_scope, const char *key, ResultSet &results) {468  bool result = false;469 470  Target *target = exe_scope->CalculateTarget().get();471  if (target) {472    const auto &images(target->GetImages());473    TypeQuery query(key);474    TypeResults type_results;475    images.FindTypes(nullptr, query, type_results);476    for (const auto &match : type_results.GetTypeMap().Types()) {477      if (match) {478        CompilerType compiler_type(match->GetFullCompilerType());479        compiler_type = AdjustForInclusion(compiler_type);480        if (!compiler_type)481          continue;482        std::unique_ptr<Language::TypeScavenger::Result> scavengeresult(483            new Result(compiler_type));484        results.insert(std::move(scavengeresult));485        result = true;486      }487    }488  }489 490  return result;491}492 493std::pair<llvm::StringRef, llvm::StringRef>494Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {495  return std::pair<llvm::StringRef, llvm::StringRef>();496}497 498bool Language::DemangledNameContainsPath(llvm::StringRef path,499                                         ConstString demangled) const {500  // The base implementation does a simple contains comparision:501  if (path.empty())502    return false;503  return demangled.GetStringRef().contains(path);504}505 506DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {507  return nullptr;508}509 510LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) {511  return eLazyBoolCalculate;512}513 514bool Language::IsNilReference(ValueObject &valobj) { return false; }515 516bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }517 518bool Language::GetFunctionDisplayName(const SymbolContext &sc,519                                      const ExecutionContext *exe_ctx,520                                      FunctionNameRepresentation representation,521                                      Stream &s) {522  return false;523}524 525void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on,526                                               Stream &s) {527  GetDefaultExceptionResolverDescription(catch_on, throw_on, s);528}529 530void Language::GetDefaultExceptionResolverDescription(bool catch_on,531                                                      bool throw_on,532                                                      Stream &s) {533  s.Printf("Exception breakpoint (catch: %s throw: %s)",534           catch_on ? "on" : "off", throw_on ? "on" : "off");535}536 537std::optional<bool> Language::GetBooleanFromString(llvm::StringRef str) const {538  return llvm::StringSwitch<std::optional<bool>>(str)539      .Case("true", {true})540      .Case("false", {false})541      .Default({});542}543 544// Constructor545Language::Language() = default;546 547// Destructor548Language::~Language() = default;549 550static std::optional<llvm::dwarf::SourceLanguage>551ToDwarfSourceLanguage(lldb::LanguageType language_type) {552  if (language_type <= lldb::eLanguageTypeLastStandardLanguage)553    return static_cast<llvm::dwarf::SourceLanguage>(language_type);554 555  switch (language_type) {556  case eLanguageTypeMipsAssembler:557    return llvm::dwarf::DW_LANG_Mips_Assembler;558  default:559    return std::nullopt;560  }561}562 563SourceLanguage::SourceLanguage(lldb::LanguageType language_type) {564  std::optional<llvm::dwarf::SourceLanguage> dwarf_lang =565      ToDwarfSourceLanguage(language_type);566  if (!dwarf_lang)567    return;568 569  auto lname = llvm::dwarf::toDW_LNAME(*dwarf_lang);570  if (!lname)571    return;572  name = lname->first;573  version = lname->second;574}575 576lldb::LanguageType SourceLanguage::AsLanguageType() const {577  if (auto lang = llvm::dwarf::toDW_LANG((llvm::dwarf::SourceLanguageName)name,578                                         version))579    return (lldb::LanguageType)*lang;580  return lldb::eLanguageTypeUnknown;581}582 583llvm::StringRef SourceLanguage::GetDescription() const {584  return llvm::dwarf::LanguageDescription(585      static_cast<llvm::dwarf::SourceLanguageName>(name), version);586}587bool SourceLanguage::IsC() const { return name == llvm::dwarf::DW_LNAME_C; }588 589bool SourceLanguage::IsObjC() const {590  return name == llvm::dwarf::DW_LNAME_ObjC;591}592 593bool SourceLanguage::IsCPlusPlus() const {594  return name == llvm::dwarf::DW_LNAME_C_plus_plus;595}596