1061da546Spatrick //===-- Language.h ---------------------------------------------------*- C++ 2061da546Spatrick //-*-===// 3061da546Spatrick // 4061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 6061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7061da546Spatrick // 8061da546Spatrick //===----------------------------------------------------------------------===// 9061da546Spatrick 10dda28197Spatrick #ifndef LLDB_TARGET_LANGUAGE_H 11dda28197Spatrick #define LLDB_TARGET_LANGUAGE_H 12061da546Spatrick 13061da546Spatrick #include <functional> 14061da546Spatrick #include <memory> 15061da546Spatrick #include <set> 16061da546Spatrick #include <vector> 17061da546Spatrick 18061da546Spatrick #include "lldb/Core/Highlighter.h" 19061da546Spatrick #include "lldb/Core/PluginInterface.h" 20061da546Spatrick #include "lldb/DataFormatters/DumpValueObjectOptions.h" 21061da546Spatrick #include "lldb/DataFormatters/FormatClasses.h" 22061da546Spatrick #include "lldb/DataFormatters/StringPrinter.h" 23061da546Spatrick #include "lldb/Symbol/TypeSystem.h" 24061da546Spatrick #include "lldb/lldb-private.h" 25061da546Spatrick #include "lldb/lldb-public.h" 26061da546Spatrick 27061da546Spatrick namespace lldb_private { 28061da546Spatrick 29061da546Spatrick class Language : public PluginInterface { 30061da546Spatrick public: 31061da546Spatrick class TypeScavenger { 32061da546Spatrick public: 33061da546Spatrick class Result { 34061da546Spatrick public: 35061da546Spatrick virtual bool IsValid() = 0; 36061da546Spatrick 37061da546Spatrick virtual bool DumpToStream(Stream &stream, 38061da546Spatrick bool print_help_if_available) = 0; 39061da546Spatrick 40061da546Spatrick virtual ~Result() = default; 41061da546Spatrick }; 42061da546Spatrick 43061da546Spatrick typedef std::set<std::unique_ptr<Result>> ResultSet; 44061da546Spatrick 45061da546Spatrick virtual ~TypeScavenger() = default; 46061da546Spatrick 47061da546Spatrick size_t Find(ExecutionContextScope *exe_scope, const char *key, 48061da546Spatrick ResultSet &results, bool append = true); 49061da546Spatrick 50061da546Spatrick protected: 51061da546Spatrick TypeScavenger() = default; 52061da546Spatrick 53061da546Spatrick virtual bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 54061da546Spatrick ResultSet &results) = 0; 55061da546Spatrick }; 56061da546Spatrick 57061da546Spatrick class ImageListTypeScavenger : public TypeScavenger { 58061da546Spatrick class Result : public Language::TypeScavenger::Result { 59061da546Spatrick public: Result(CompilerType type)60*f6aab3d8Srobert Result(CompilerType type) : m_compiler_type(type) {} 61061da546Spatrick IsValid()62061da546Spatrick bool IsValid() override { return m_compiler_type.IsValid(); } 63061da546Spatrick DumpToStream(Stream & stream,bool print_help_if_available)64061da546Spatrick bool DumpToStream(Stream &stream, bool print_help_if_available) override { 65061da546Spatrick if (IsValid()) { 66061da546Spatrick m_compiler_type.DumpTypeDescription(&stream); 67061da546Spatrick stream.EOL(); 68061da546Spatrick return true; 69061da546Spatrick } 70061da546Spatrick return false; 71061da546Spatrick } 72061da546Spatrick 73061da546Spatrick ~Result() override = default; 74061da546Spatrick 75061da546Spatrick private: 76061da546Spatrick CompilerType m_compiler_type; 77061da546Spatrick }; 78061da546Spatrick 79061da546Spatrick protected: 80061da546Spatrick ImageListTypeScavenger() = default; 81061da546Spatrick 82061da546Spatrick ~ImageListTypeScavenger() override = default; 83061da546Spatrick 84061da546Spatrick // is this type something we should accept? it's usually going to be a 85061da546Spatrick // filter by language + maybe some sugar tweaking 86061da546Spatrick // returning an empty type means rejecting this candidate entirely; 87061da546Spatrick // any other result will be accepted as a valid match 88061da546Spatrick virtual CompilerType AdjustForInclusion(CompilerType &candidate) = 0; 89061da546Spatrick 90061da546Spatrick bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 91061da546Spatrick ResultSet &results) override; 92061da546Spatrick }; 93061da546Spatrick 94061da546Spatrick template <typename... ScavengerTypes> 95061da546Spatrick class EitherTypeScavenger : public TypeScavenger { 96061da546Spatrick public: EitherTypeScavenger()97*f6aab3d8Srobert EitherTypeScavenger() : TypeScavenger() { 98061da546Spatrick for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { 99061da546Spatrick if (scavenger) 100061da546Spatrick m_scavengers.push_back(scavenger); 101061da546Spatrick } 102061da546Spatrick } 103061da546Spatrick protected: Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)104061da546Spatrick bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 105061da546Spatrick ResultSet &results) override { 106061da546Spatrick const bool append = false; 107061da546Spatrick for (auto& scavenger : m_scavengers) { 108061da546Spatrick if (scavenger && scavenger->Find(exe_scope, key, results, append)) 109061da546Spatrick return true; 110061da546Spatrick } 111061da546Spatrick return false; 112061da546Spatrick } 113061da546Spatrick private: 114061da546Spatrick std::vector<std::shared_ptr<TypeScavenger>> m_scavengers; 115061da546Spatrick }; 116061da546Spatrick 117061da546Spatrick template <typename... ScavengerTypes> 118061da546Spatrick class UnionTypeScavenger : public TypeScavenger { 119061da546Spatrick public: UnionTypeScavenger()120*f6aab3d8Srobert UnionTypeScavenger() : TypeScavenger() { 121061da546Spatrick for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { 122061da546Spatrick if (scavenger) 123061da546Spatrick m_scavengers.push_back(scavenger); 124061da546Spatrick } 125061da546Spatrick } 126061da546Spatrick protected: Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)127061da546Spatrick bool Find_Impl(ExecutionContextScope *exe_scope, const char *key, 128061da546Spatrick ResultSet &results) override { 129061da546Spatrick const bool append = true; 130061da546Spatrick bool success = false; 131061da546Spatrick for (auto& scavenger : m_scavengers) { 132061da546Spatrick if (scavenger) 133061da546Spatrick success = scavenger->Find(exe_scope, key, results, append) || success; 134061da546Spatrick } 135061da546Spatrick return success; 136061da546Spatrick } 137061da546Spatrick private: 138061da546Spatrick std::vector<std::shared_ptr<TypeScavenger>> m_scavengers; 139061da546Spatrick }; 140061da546Spatrick 141061da546Spatrick enum class FunctionNameRepresentation { 142061da546Spatrick eName, 143061da546Spatrick eNameWithArgs, 144061da546Spatrick eNameWithNoArgs 145061da546Spatrick }; 146061da546Spatrick 147061da546Spatrick ~Language() override; 148061da546Spatrick 149061da546Spatrick static Language *FindPlugin(lldb::LanguageType language); 150061da546Spatrick 151061da546Spatrick /// Returns the Language associated with the given file path or a nullptr 152061da546Spatrick /// if there is no known language. 153061da546Spatrick static Language *FindPlugin(llvm::StringRef file_path); 154061da546Spatrick 155061da546Spatrick static Language *FindPlugin(lldb::LanguageType language, 156061da546Spatrick llvm::StringRef file_path); 157061da546Spatrick 158061da546Spatrick // return false from callback to stop iterating 159061da546Spatrick static void ForEach(std::function<bool(Language *)> callback); 160061da546Spatrick 161061da546Spatrick virtual lldb::LanguageType GetLanguageType() const = 0; 162061da546Spatrick 163061da546Spatrick virtual bool IsTopLevelFunction(Function &function); 164061da546Spatrick 165061da546Spatrick virtual bool IsSourceFile(llvm::StringRef file_path) const = 0; 166061da546Spatrick GetHighlighter()167061da546Spatrick virtual const Highlighter *GetHighlighter() const { return nullptr; } 168061da546Spatrick 169061da546Spatrick virtual lldb::TypeCategoryImplSP GetFormatters(); 170061da546Spatrick 171061da546Spatrick virtual HardcodedFormatters::HardcodedFormatFinder GetHardcodedFormats(); 172061da546Spatrick 173061da546Spatrick virtual HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries(); 174061da546Spatrick 175061da546Spatrick virtual HardcodedFormatters::HardcodedSyntheticFinder 176061da546Spatrick GetHardcodedSynthetics(); 177061da546Spatrick 178*f6aab3d8Srobert virtual std::vector<FormattersMatchCandidate> 179061da546Spatrick GetPossibleFormattersMatches(ValueObject &valobj, 180061da546Spatrick lldb::DynamicValueType use_dynamic); 181061da546Spatrick 182061da546Spatrick virtual std::unique_ptr<TypeScavenger> GetTypeScavenger(); 183061da546Spatrick 184061da546Spatrick virtual const char *GetLanguageSpecificTypeLookupHelp(); 185061da546Spatrick 186be691f3bSpatrick class MethodNameVariant { 187be691f3bSpatrick ConstString m_name; 188be691f3bSpatrick lldb::FunctionNameType m_type; 189be691f3bSpatrick 190be691f3bSpatrick public: MethodNameVariant(ConstString name,lldb::FunctionNameType type)191be691f3bSpatrick MethodNameVariant(ConstString name, lldb::FunctionNameType type) 192be691f3bSpatrick : m_name(name), m_type(type) {} GetName()193be691f3bSpatrick ConstString GetName() const { return m_name; } GetType()194be691f3bSpatrick lldb::FunctionNameType GetType() const { return m_type; } 195be691f3bSpatrick }; 196061da546Spatrick // If a language can have more than one possible name for a method, this 197061da546Spatrick // function can be used to enumerate them. This is useful when doing name 198061da546Spatrick // lookups. 199be691f3bSpatrick virtual std::vector<Language::MethodNameVariant> GetMethodNameVariants(ConstString method_name)200061da546Spatrick GetMethodNameVariants(ConstString method_name) const { 201be691f3bSpatrick return std::vector<Language::MethodNameVariant>(); 202061da546Spatrick }; 203061da546Spatrick 204be691f3bSpatrick /// Returns true iff the given symbol name is compatible with the mangling 205be691f3bSpatrick /// scheme of this language. 206be691f3bSpatrick /// 207be691f3bSpatrick /// This function should only return true if there is a high confidence 208be691f3bSpatrick /// that the name actually belongs to this language. SymbolNameFitsToLanguage(Mangled name)209be691f3bSpatrick virtual bool SymbolNameFitsToLanguage(Mangled name) const { return false; } 210be691f3bSpatrick 211061da546Spatrick // if an individual data formatter can apply to several types and cross a 212061da546Spatrick // language boundary it makes sense for individual languages to want to 213061da546Spatrick // customize the printing of values of that type by appending proper 214061da546Spatrick // prefix/suffix information in language-specific ways 215061da546Spatrick virtual bool GetFormatterPrefixSuffix(ValueObject &valobj, 216061da546Spatrick ConstString type_hint, 217061da546Spatrick std::string &prefix, 218061da546Spatrick std::string &suffix); 219061da546Spatrick 220*f6aab3d8Srobert // When looking up functions, we take a user provided string which may be a 221*f6aab3d8Srobert // partial match to the full demangled name and compare it to the actual 222*f6aab3d8Srobert // demangled name to see if it matches as much as the user specified. An 223*f6aab3d8Srobert // example of this is if the user provided A::my_function, but the 224*f6aab3d8Srobert // symbol was really B::A::my_function. We want that to be 225*f6aab3d8Srobert // a match. But we wouldn't want this to match AnotherA::my_function. The 226*f6aab3d8Srobert // user is specifying a truncated path, not a truncated set of characters. 227*f6aab3d8Srobert // This function does a language-aware comparison for those purposes. 228*f6aab3d8Srobert virtual bool DemangledNameContainsPath(llvm::StringRef path, 229*f6aab3d8Srobert ConstString demangled) const; 230*f6aab3d8Srobert 231061da546Spatrick // if a language has a custom format for printing variable declarations that 232061da546Spatrick // it wants LLDB to honor it should return an appropriate closure here 233061da546Spatrick virtual DumpValueObjectOptions::DeclPrintingHelper GetDeclPrintingHelper(); 234061da546Spatrick 235061da546Spatrick virtual LazyBool IsLogicalTrue(ValueObject &valobj, Status &error); 236061da546Spatrick 237061da546Spatrick // for a ValueObject of some "reference type", if the value points to the 238061da546Spatrick // nil/null object, this method returns true 239061da546Spatrick virtual bool IsNilReference(ValueObject &valobj); 240061da546Spatrick 241be691f3bSpatrick /// Returns the summary string for ValueObjects for which IsNilReference() is 242be691f3bSpatrick /// true. GetNilReferenceSummaryString()243be691f3bSpatrick virtual llvm::StringRef GetNilReferenceSummaryString() { return {}; } 244be691f3bSpatrick 245061da546Spatrick // for a ValueObject of some "reference type", if the language provides a 246061da546Spatrick // technique to decide whether the reference has ever been assigned to some 247061da546Spatrick // object, this method will return true if such detection is possible, and if 248061da546Spatrick // the reference has never been assigned 249061da546Spatrick virtual bool IsUninitializedReference(ValueObject &valobj); 250061da546Spatrick 251061da546Spatrick virtual bool GetFunctionDisplayName(const SymbolContext *sc, 252061da546Spatrick const ExecutionContext *exe_ctx, 253061da546Spatrick FunctionNameRepresentation representation, 254061da546Spatrick Stream &s); 255061da546Spatrick 256*f6aab3d8Srobert virtual ConstString GetDemangledFunctionNameWithoutArguments(Mangled mangled)257*f6aab3d8Srobert GetDemangledFunctionNameWithoutArguments(Mangled mangled) const { 258*f6aab3d8Srobert if (ConstString demangled = mangled.GetDemangledName()) 259*f6aab3d8Srobert return demangled; 260*f6aab3d8Srobert 261*f6aab3d8Srobert return mangled.GetMangledName(); 262*f6aab3d8Srobert } 263*f6aab3d8Srobert 264061da546Spatrick virtual void GetExceptionResolverDescription(bool catch_on, bool throw_on, 265061da546Spatrick Stream &s); 266061da546Spatrick 267061da546Spatrick static void GetDefaultExceptionResolverDescription(bool catch_on, 268061da546Spatrick bool throw_on, Stream &s); 269061da546Spatrick 270061da546Spatrick // These are accessors for general information about the Languages lldb knows 271061da546Spatrick // about: 272061da546Spatrick 273061da546Spatrick static lldb::LanguageType 274061da546Spatrick GetLanguageTypeFromString(const char *string) = delete; 275061da546Spatrick static lldb::LanguageType GetLanguageTypeFromString(llvm::StringRef string); 276061da546Spatrick 277061da546Spatrick static const char *GetNameForLanguageType(lldb::LanguageType language); 278061da546Spatrick 279061da546Spatrick static void PrintAllLanguages(Stream &s, const char *prefix, 280061da546Spatrick const char *suffix); 281061da546Spatrick 282*f6aab3d8Srobert /// Prints to the specified stream 's' each language type that the 283*f6aab3d8Srobert /// current target supports for expression evaluation. 284*f6aab3d8Srobert /// 285*f6aab3d8Srobert /// \param[out] s Stream to which the language types are written. 286*f6aab3d8Srobert /// \param[in] prefix String that is prepended to the language type. 287*f6aab3d8Srobert /// \param[in] suffix String that is appended to the language type. 288*f6aab3d8Srobert static void PrintSupportedLanguagesForExpressions(Stream &s, 289*f6aab3d8Srobert llvm::StringRef prefix, 290*f6aab3d8Srobert llvm::StringRef suffix); 291*f6aab3d8Srobert 292061da546Spatrick // return false from callback to stop iterating 293061da546Spatrick static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback); 294061da546Spatrick 295061da546Spatrick static bool LanguageIsCPlusPlus(lldb::LanguageType language); 296061da546Spatrick 297061da546Spatrick static bool LanguageIsObjC(lldb::LanguageType language); 298061da546Spatrick 299061da546Spatrick static bool LanguageIsC(lldb::LanguageType language); 300061da546Spatrick 301061da546Spatrick /// Equivalent to \c LanguageIsC||LanguageIsObjC||LanguageIsCPlusPlus. 302061da546Spatrick static bool LanguageIsCFamily(lldb::LanguageType language); 303061da546Spatrick 304061da546Spatrick static bool LanguageIsPascal(lldb::LanguageType language); 305061da546Spatrick 306061da546Spatrick // return the primary language, so if LanguageIsC(l), return eLanguageTypeC, 307061da546Spatrick // etc. 308061da546Spatrick static lldb::LanguageType GetPrimaryLanguage(lldb::LanguageType language); 309061da546Spatrick 310061da546Spatrick static std::set<lldb::LanguageType> GetSupportedLanguages(); 311061da546Spatrick 312061da546Spatrick static LanguageSet GetLanguagesSupportingTypeSystems(); 313061da546Spatrick static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions(); 314061da546Spatrick static LanguageSet GetLanguagesSupportingREPLs(); 315061da546Spatrick 316*f6aab3d8Srobert // Given a mangled function name, calculates some alternative manglings since 317*f6aab3d8Srobert // the compiler mangling may not line up with the symbol we are expecting. 318*f6aab3d8Srobert virtual std::vector<ConstString> GenerateAlternateFunctionManglings(const ConstString mangled)319*f6aab3d8Srobert GenerateAlternateFunctionManglings(const ConstString mangled) const { 320*f6aab3d8Srobert return std::vector<ConstString>(); 321*f6aab3d8Srobert } 322*f6aab3d8Srobert 323*f6aab3d8Srobert virtual ConstString FindBestAlternateFunctionMangledName(const Mangled mangled,const SymbolContext & sym_ctx)324*f6aab3d8Srobert FindBestAlternateFunctionMangledName(const Mangled mangled, 325*f6aab3d8Srobert const SymbolContext &sym_ctx) const { 326*f6aab3d8Srobert return ConstString(); 327*f6aab3d8Srobert } 328*f6aab3d8Srobert 329061da546Spatrick protected: 330061da546Spatrick // Classes that inherit from Language can see and modify these 331061da546Spatrick 332061da546Spatrick Language(); 333061da546Spatrick 334061da546Spatrick private: 335dda28197Spatrick Language(const Language &) = delete; 336dda28197Spatrick const Language &operator=(const Language &) = delete; 337061da546Spatrick }; 338061da546Spatrick 339061da546Spatrick } // namespace lldb_private 340061da546Spatrick 341dda28197Spatrick #endif // LLDB_TARGET_LANGUAGE_H 342