xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/Language.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- Language.h ---------------------------------------------------*- C++
2 //-*-===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLDB_TARGET_LANGUAGE_H
11 #define LLDB_TARGET_LANGUAGE_H
12 
13 #include <functional>
14 #include <memory>
15 #include <set>
16 #include <vector>
17 
18 #include "lldb/Core/Highlighter.h"
19 #include "lldb/Core/PluginInterface.h"
20 #include "lldb/DataFormatters/DumpValueObjectOptions.h"
21 #include "lldb/DataFormatters/FormatClasses.h"
22 #include "lldb/DataFormatters/StringPrinter.h"
23 #include "lldb/Symbol/TypeSystem.h"
24 #include "lldb/lldb-private.h"
25 #include "lldb/lldb-public.h"
26 
27 namespace lldb_private {
28 
29 class LanguageProperties : public Properties {
30 public:
31   LanguageProperties();
32 
33   static llvm::StringRef GetSettingName();
34 
35   bool GetEnableFilterForLineBreakpoints() const;
36 };
37 
38 class Language : public PluginInterface {
39 public:
40   class TypeScavenger {
41   public:
42     class Result {
43     public:
44       virtual bool IsValid() = 0;
45 
46       virtual bool DumpToStream(Stream &stream,
47                                 bool print_help_if_available) = 0;
48 
49       virtual ~Result() = default;
50     };
51 
52     typedef std::set<std::unique_ptr<Result>> ResultSet;
53 
54     virtual ~TypeScavenger() = default;
55 
56     size_t Find(ExecutionContextScope *exe_scope, const char *key,
57                 ResultSet &results, bool append = true);
58 
59   protected:
60     TypeScavenger() = default;
61 
62     virtual bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
63                            ResultSet &results) = 0;
64   };
65 
66   class ImageListTypeScavenger : public TypeScavenger {
67     class Result : public Language::TypeScavenger::Result {
68     public:
Result(CompilerType type)69       Result(CompilerType type) : m_compiler_type(type) {}
70 
IsValid()71       bool IsValid() override { return m_compiler_type.IsValid(); }
72 
DumpToStream(Stream & stream,bool print_help_if_available)73       bool DumpToStream(Stream &stream, bool print_help_if_available) override {
74         if (IsValid()) {
75           m_compiler_type.DumpTypeDescription(&stream);
76           stream.EOL();
77           return true;
78         }
79         return false;
80       }
81 
82       ~Result() override = default;
83 
84     private:
85       CompilerType m_compiler_type;
86     };
87 
88   protected:
89     ImageListTypeScavenger() = default;
90 
91     ~ImageListTypeScavenger() override = default;
92 
93     // is this type something we should accept? it's usually going to be a
94     // filter by language + maybe some sugar tweaking
95     // returning an empty type means rejecting this candidate entirely;
96     // any other result will be accepted as a valid match
97     virtual CompilerType AdjustForInclusion(CompilerType &candidate) = 0;
98 
99     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
100                    ResultSet &results) override;
101   };
102 
103   template <typename... ScavengerTypes>
104   class EitherTypeScavenger : public TypeScavenger {
105   public:
EitherTypeScavenger()106     EitherTypeScavenger() : TypeScavenger() {
107       for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) {
108         if (scavenger)
109           m_scavengers.push_back(scavenger);
110       }
111     }
112   protected:
Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)113     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
114                    ResultSet &results) override {
115       const bool append = false;
116       for (auto& scavenger : m_scavengers) {
117         if (scavenger && scavenger->Find(exe_scope, key, results, append))
118           return true;
119       }
120       return false;
121     }
122   private:
123     std::vector<std::shared_ptr<TypeScavenger>> m_scavengers;
124   };
125 
126   template <typename... ScavengerTypes>
127   class UnionTypeScavenger : public TypeScavenger {
128   public:
UnionTypeScavenger()129     UnionTypeScavenger() : TypeScavenger() {
130       for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) {
131         if (scavenger)
132           m_scavengers.push_back(scavenger);
133       }
134     }
135   protected:
Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)136     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
137                    ResultSet &results) override {
138       const bool append = true;
139       bool success = false;
140       for (auto& scavenger : m_scavengers) {
141         if (scavenger)
142           success = scavenger->Find(exe_scope, key, results, append) || success;
143       }
144       return success;
145     }
146   private:
147     std::vector<std::shared_ptr<TypeScavenger>> m_scavengers;
148   };
149 
150   enum class FunctionNameRepresentation {
151     eName,
152     eNameWithArgs,
153     eNameWithNoArgs
154   };
155 
156   ~Language() override;
157 
158   static Language *FindPlugin(lldb::LanguageType language);
159 
160   /// Returns the Language associated with the given file path or a nullptr
161   /// if there is no known language.
162   static Language *FindPlugin(llvm::StringRef file_path);
163 
164   static Language *FindPlugin(lldb::LanguageType language,
165                               llvm::StringRef file_path);
166 
167   // return false from callback to stop iterating
168   static void ForEach(std::function<bool(Language *)> callback);
169 
170   virtual lldb::LanguageType GetLanguageType() const = 0;
171 
172   // Implement this function to return the user-defined entry point name
173   // for the language.
GetUserEntryPointName()174   virtual llvm::StringRef GetUserEntryPointName() const { return {}; }
175 
176   virtual bool IsTopLevelFunction(Function &function);
177 
178   virtual bool IsSourceFile(llvm::StringRef file_path) const = 0;
179 
GetHighlighter()180   virtual const Highlighter *GetHighlighter() const { return nullptr; }
181 
182   virtual lldb::TypeCategoryImplSP GetFormatters();
183 
184   virtual HardcodedFormatters::HardcodedFormatFinder GetHardcodedFormats();
185 
186   virtual HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries();
187 
188   virtual HardcodedFormatters::HardcodedSyntheticFinder
189   GetHardcodedSynthetics();
190 
191   virtual std::vector<FormattersMatchCandidate>
192   GetPossibleFormattersMatches(ValueObject &valobj,
193                                lldb::DynamicValueType use_dynamic);
194 
195   virtual std::unique_ptr<TypeScavenger> GetTypeScavenger();
196 
197   virtual const char *GetLanguageSpecificTypeLookupHelp();
198 
199   class MethodNameVariant {
200     ConstString m_name;
201     lldb::FunctionNameType m_type;
202 
203   public:
MethodNameVariant(ConstString name,lldb::FunctionNameType type)204     MethodNameVariant(ConstString name, lldb::FunctionNameType type)
205         : m_name(name), m_type(type) {}
GetName()206     ConstString GetName() const { return m_name; }
GetType()207     lldb::FunctionNameType GetType() const { return m_type; }
208   };
209   // If a language can have more than one possible name for a method, this
210   // function can be used to enumerate them. This is useful when doing name
211   // lookups.
212   virtual std::vector<Language::MethodNameVariant>
GetMethodNameVariants(ConstString method_name)213   GetMethodNameVariants(ConstString method_name) const {
214     return std::vector<Language::MethodNameVariant>();
215   };
216 
217   /// Returns true iff the given symbol name is compatible with the mangling
218   /// scheme of this language.
219   ///
220   /// This function should only return true if there is a high confidence
221   /// that the name actually belongs to this language.
SymbolNameFitsToLanguage(Mangled name)222   virtual bool SymbolNameFitsToLanguage(Mangled name) const { return false; }
223 
224   /// An individual data formatter may apply to several types and cross language
225   /// boundaries. Each of those languages may want to customize the display of
226   /// values of said types by appending proper prefix/suffix information in
227   /// language-specific ways. This function returns that prefix and suffix.
228   ///
229   /// \param[in] type_hint
230   ///   A StringRef used to determine what the prefix and suffix should be. It
231   ///   is called a hint because some types may have multiple variants for which
232   ///   the prefix and/or suffix may vary.
233   ///
234   /// \return
235   ///   A std::pair<StringRef, StringRef>, the first being the prefix and the
236   ///   second being the suffix. They may be empty.
237   virtual std::pair<llvm::StringRef, llvm::StringRef>
238   GetFormatterPrefixSuffix(llvm::StringRef type_hint);
239 
240   // When looking up functions, we take a user provided string which may be a
241   // partial match to the full demangled name and compare it to the actual
242   // demangled name to see if it matches as much as the user specified.  An
243   // example of this is if the user provided A::my_function, but the
244   // symbol was really B::A::my_function.  We want that to be
245   // a match.  But we wouldn't want this to match AnotherA::my_function.  The
246   // user is specifying a truncated path, not a truncated set of characters.
247   // This function does a language-aware comparison for those purposes.
248   virtual bool DemangledNameContainsPath(llvm::StringRef path,
249                                          ConstString demangled) const;
250 
251   // if a language has a custom format for printing variable declarations that
252   // it wants LLDB to honor it should return an appropriate closure here
253   virtual DumpValueObjectOptions::DeclPrintingHelper GetDeclPrintingHelper();
254 
255   virtual LazyBool IsLogicalTrue(ValueObject &valobj, Status &error);
256 
257   // for a ValueObject of some "reference type", if the value points to the
258   // nil/null object, this method returns true
259   virtual bool IsNilReference(ValueObject &valobj);
260 
261   /// Returns the summary string for ValueObjects for which IsNilReference() is
262   /// true.
GetNilReferenceSummaryString()263   virtual llvm::StringRef GetNilReferenceSummaryString() { return {}; }
264 
265   // for a ValueObject of some "reference type", if the language provides a
266   // technique to decide whether the reference has ever been assigned to some
267   // object, this method will return true if such detection is possible, and if
268   // the reference has never been assigned
269   virtual bool IsUninitializedReference(ValueObject &valobj);
270 
271   virtual bool GetFunctionDisplayName(const SymbolContext *sc,
272                                       const ExecutionContext *exe_ctx,
273                                       FunctionNameRepresentation representation,
274                                       Stream &s);
275 
276   virtual ConstString
GetDemangledFunctionNameWithoutArguments(Mangled mangled)277   GetDemangledFunctionNameWithoutArguments(Mangled mangled) const {
278     if (ConstString demangled = mangled.GetDemangledName())
279       return demangled;
280 
281     return mangled.GetMangledName();
282   }
283 
GetDisplayDemangledName(Mangled mangled)284   virtual ConstString GetDisplayDemangledName(Mangled mangled) const {
285     return mangled.GetDemangledName();
286   }
287 
288   virtual void GetExceptionResolverDescription(bool catch_on, bool throw_on,
289                                                Stream &s);
290 
291   static void GetDefaultExceptionResolverDescription(bool catch_on,
292                                                      bool throw_on, Stream &s);
293 
294   // These are accessors for general information about the Languages lldb knows
295   // about:
296 
297   static lldb::LanguageType
298   GetLanguageTypeFromString(const char *string) = delete;
299   static lldb::LanguageType GetLanguageTypeFromString(llvm::StringRef string);
300 
301   static const char *GetNameForLanguageType(lldb::LanguageType language);
302 
303   static void PrintAllLanguages(Stream &s, const char *prefix,
304                                 const char *suffix);
305 
306   /// Prints to the specified stream 's' each language type that the
307   /// current target supports for expression evaluation.
308   ///
309   /// \param[out] s      Stream to which the language types are written.
310   /// \param[in]  prefix String that is prepended to the language type.
311   /// \param[in]  suffix String that is appended to the language type.
312   static void PrintSupportedLanguagesForExpressions(Stream &s,
313                                                     llvm::StringRef prefix,
314                                                     llvm::StringRef suffix);
315 
316   // return false from callback to stop iterating
317   static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback);
318 
319   static bool LanguageIsCPlusPlus(lldb::LanguageType language);
320 
321   static bool LanguageIsObjC(lldb::LanguageType language);
322 
323   static bool LanguageIsC(lldb::LanguageType language);
324 
325   /// Equivalent to \c LanguageIsC||LanguageIsObjC||LanguageIsCPlusPlus.
326   static bool LanguageIsCFamily(lldb::LanguageType language);
327 
328   static bool LanguageIsPascal(lldb::LanguageType language);
329 
330   // return the primary language, so if LanguageIsC(l), return eLanguageTypeC,
331   // etc.
332   static lldb::LanguageType GetPrimaryLanguage(lldb::LanguageType language);
333 
334   static std::set<lldb::LanguageType> GetSupportedLanguages();
335 
336   static LanguageSet GetLanguagesSupportingTypeSystems();
337   static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions();
338   static LanguageSet GetLanguagesSupportingREPLs();
339 
340   static LanguageProperties &GetGlobalLanguageProperties();
341 
342   // Given a mangled function name, calculates some alternative manglings since
343   // the compiler mangling may not line up with the symbol we are expecting.
344   virtual std::vector<ConstString>
GenerateAlternateFunctionManglings(const ConstString mangled)345   GenerateAlternateFunctionManglings(const ConstString mangled) const {
346     return std::vector<ConstString>();
347   }
348 
349   virtual ConstString
FindBestAlternateFunctionMangledName(const Mangled mangled,const SymbolContext & sym_ctx)350   FindBestAlternateFunctionMangledName(const Mangled mangled,
351                                        const SymbolContext &sym_ctx) const {
352     return ConstString();
353   }
354 
GetInstanceVariableName()355   virtual llvm::StringRef GetInstanceVariableName() { return {}; }
356 
357   /// Returns true if this SymbolContext should be ignored when setting
358   /// breakpoints by line (number or regex). Helpful for languages that create
359   /// artificial functions without meaningful user code associated with them
360   /// (e.g. code that gets expanded in late compilation stages, like by
361   /// CoroSplitter).
IgnoreForLineBreakpoints(const SymbolContext &)362   virtual bool IgnoreForLineBreakpoints(const SymbolContext &) const {
363     return false;
364   }
365 
366   /// Returns true if this Language supports exception breakpoints on throw via
367   /// a corresponding LanguageRuntime plugin.
SupportsExceptionBreakpointsOnThrow()368   virtual bool SupportsExceptionBreakpointsOnThrow() const { return false; }
369 
370   /// Returns true if this Language supports exception breakpoints on catch via
371   /// a corresponding LanguageRuntime plugin.
SupportsExceptionBreakpointsOnCatch()372   virtual bool SupportsExceptionBreakpointsOnCatch() const { return false; }
373 
374   /// Returns the keyword used for throw statements in this language, e.g.
375   /// Python uses \b raise. Defaults to \b throw.
GetThrowKeyword()376   virtual llvm::StringRef GetThrowKeyword() const { return "throw"; }
377 
378   /// Returns the keyword used for catch statements in this language, e.g.
379   /// Python uses \b except. Defaults to \b catch.
GetCatchKeyword()380   virtual llvm::StringRef GetCatchKeyword() const { return "catch"; }
381 
382 protected:
383   // Classes that inherit from Language can see and modify these
384 
385   Language();
386 
387 private:
388   Language(const Language &) = delete;
389   const Language &operator=(const Language &) = delete;
390 };
391 
392 } // namespace lldb_private
393 
394 #endif // LLDB_TARGET_LANGUAGE_H
395