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