xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/Language.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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/FormatEntity.h"
19 #include "lldb/Core/Highlighter.h"
20 #include "lldb/Core/PluginInterface.h"
21 #include "lldb/DataFormatters/DumpValueObjectOptions.h"
22 #include "lldb/DataFormatters/FormatClasses.h"
23 #include "lldb/DataFormatters/StringPrinter.h"
24 #include "lldb/Symbol/TypeSystem.h"
25 #include "lldb/lldb-private.h"
26 #include "lldb/lldb-public.h"
27 
28 namespace lldb_private {
29 
30 class LanguageProperties : public Properties {
31 public:
32   LanguageProperties();
33 
34   static llvm::StringRef GetSettingName();
35 
36   bool GetEnableFilterForLineBreakpoints() const;
37 };
38 
39 class Language : public PluginInterface {
40 public:
41   class TypeScavenger {
42   public:
43     class Result {
44     public:
45       virtual bool IsValid() = 0;
46 
47       virtual bool DumpToStream(Stream &stream,
48                                 bool print_help_if_available) = 0;
49 
50       virtual ~Result() = default;
51     };
52 
53     typedef std::set<std::unique_ptr<Result>> ResultSet;
54 
55     virtual ~TypeScavenger() = default;
56 
57     size_t Find(ExecutionContextScope *exe_scope, const char *key,
58                 ResultSet &results, bool append = true);
59 
60   protected:
61     TypeScavenger() = default;
62 
63     virtual bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
64                            ResultSet &results) = 0;
65   };
66 
67   class ImageListTypeScavenger : public TypeScavenger {
68     class Result : public Language::TypeScavenger::Result {
69     public:
Result(CompilerType type)70       Result(CompilerType type) : m_compiler_type(type) {}
71 
IsValid()72       bool IsValid() override { return m_compiler_type.IsValid(); }
73 
DumpToStream(Stream & stream,bool print_help_if_available)74       bool DumpToStream(Stream &stream, bool print_help_if_available) override {
75         if (IsValid()) {
76           m_compiler_type.DumpTypeDescription(&stream);
77           stream.EOL();
78           return true;
79         }
80         return false;
81       }
82 
83       ~Result() override = default;
84 
85     private:
86       CompilerType m_compiler_type;
87     };
88 
89   protected:
90     ImageListTypeScavenger() = default;
91 
92     ~ImageListTypeScavenger() override = default;
93 
94     // is this type something we should accept? it's usually going to be a
95     // filter by language + maybe some sugar tweaking
96     // returning an empty type means rejecting this candidate entirely;
97     // any other result will be accepted as a valid match
98     virtual CompilerType AdjustForInclusion(CompilerType &candidate) = 0;
99 
100     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
101                    ResultSet &results) override;
102   };
103 
104   template <typename... ScavengerTypes>
105   class EitherTypeScavenger : public TypeScavenger {
106   public:
EitherTypeScavenger()107     EitherTypeScavenger() : TypeScavenger() {
108       for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) {
109         if (scavenger)
110           m_scavengers.push_back(scavenger);
111       }
112     }
113   protected:
Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)114     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
115                    ResultSet &results) override {
116       const bool append = false;
117       for (auto& scavenger : m_scavengers) {
118         if (scavenger && scavenger->Find(exe_scope, key, results, append))
119           return true;
120       }
121       return false;
122     }
123   private:
124     std::vector<std::shared_ptr<TypeScavenger>> m_scavengers;
125   };
126 
127   template <typename... ScavengerTypes>
128   class UnionTypeScavenger : public TypeScavenger {
129   public:
UnionTypeScavenger()130     UnionTypeScavenger() : TypeScavenger() {
131       for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) {
132         if (scavenger)
133           m_scavengers.push_back(scavenger);
134       }
135     }
136   protected:
Find_Impl(ExecutionContextScope * exe_scope,const char * key,ResultSet & results)137     bool Find_Impl(ExecutionContextScope *exe_scope, const char *key,
138                    ResultSet &results) override {
139       const bool append = true;
140       bool success = false;
141       for (auto& scavenger : m_scavengers) {
142         if (scavenger)
143           success = scavenger->Find(exe_scope, key, results, append) || success;
144       }
145       return success;
146     }
147   private:
148     std::vector<std::shared_ptr<TypeScavenger>> m_scavengers;
149   };
150 
151   enum class FunctionNameRepresentation {
152     eName,
153     eNameWithArgs,
154     eNameWithNoArgs
155   };
156 
157   ~Language() override;
158 
159   static Language *FindPlugin(lldb::LanguageType language);
160 
161   /// Returns the Language associated with the given file path or a nullptr
162   /// if there is no known language.
163   static Language *FindPlugin(llvm::StringRef file_path);
164 
165   static Language *FindPlugin(lldb::LanguageType language,
166                               llvm::StringRef file_path);
167 
168   // return false from callback to stop iterating
169   static void ForEach(std::function<bool(Language *)> callback);
170 
171   virtual lldb::LanguageType GetLanguageType() const = 0;
172 
173   // Implement this function to return the user-defined entry point name
174   // for the language.
GetUserEntryPointName()175   virtual llvm::StringRef GetUserEntryPointName() const { return {}; }
176 
177   virtual bool IsTopLevelFunction(Function &function);
178 
179   virtual bool IsSourceFile(llvm::StringRef file_path) const = 0;
180 
GetHighlighter()181   virtual const Highlighter *GetHighlighter() const { return nullptr; }
182 
183   virtual lldb::TypeCategoryImplSP GetFormatters();
184 
185   virtual HardcodedFormatters::HardcodedFormatFinder GetHardcodedFormats();
186 
187   virtual HardcodedFormatters::HardcodedSummaryFinder GetHardcodedSummaries();
188 
189   virtual HardcodedFormatters::HardcodedSyntheticFinder
190   GetHardcodedSynthetics();
191 
192   virtual std::vector<FormattersMatchCandidate>
193   GetPossibleFormattersMatches(ValueObject &valobj,
194                                lldb::DynamicValueType use_dynamic);
195 
196   virtual std::unique_ptr<TypeScavenger> GetTypeScavenger();
197 
198   virtual const char *GetLanguageSpecificTypeLookupHelp();
199 
200   class MethodNameVariant {
201     ConstString m_name;
202     lldb::FunctionNameType m_type;
203 
204   public:
MethodNameVariant(ConstString name,lldb::FunctionNameType type)205     MethodNameVariant(ConstString name, lldb::FunctionNameType type)
206         : m_name(name), m_type(type) {}
GetName()207     ConstString GetName() const { return m_name; }
GetType()208     lldb::FunctionNameType GetType() const { return m_type; }
209   };
210   // If a language can have more than one possible name for a method, this
211   // function can be used to enumerate them. This is useful when doing name
212   // lookups.
213   virtual std::vector<Language::MethodNameVariant>
GetMethodNameVariants(ConstString method_name)214   GetMethodNameVariants(ConstString method_name) const {
215     return std::vector<Language::MethodNameVariant>();
216   };
217 
218   class MethodName {
219   public:
MethodName()220     MethodName() {}
221 
MethodName(ConstString full)222     MethodName(ConstString full)
223         : m_full(full), m_basename(), m_context(), m_arguments(),
224           m_qualifiers(), m_return_type(), m_scope_qualified(), m_parsed(false),
225           m_parse_error(false) {}
226 
~MethodName()227     virtual ~MethodName() {};
228 
Clear()229     void Clear() {
230       m_full.Clear();
231       m_basename = llvm::StringRef();
232       m_context = llvm::StringRef();
233       m_arguments = llvm::StringRef();
234       m_qualifiers = llvm::StringRef();
235       m_return_type = llvm::StringRef();
236       m_scope_qualified.clear();
237       m_parsed = false;
238       m_parse_error = false;
239     }
240 
IsValid()241     bool IsValid() {
242       if (!m_parsed)
243         Parse();
244       if (m_parse_error)
245         return false;
246       return (bool)m_full;
247     }
248 
GetFullName()249     ConstString GetFullName() const { return m_full; }
250 
GetBasename()251     llvm::StringRef GetBasename() {
252       if (!m_parsed)
253         Parse();
254       return m_basename;
255     }
256 
GetContext()257     llvm::StringRef GetContext() {
258       if (!m_parsed)
259         Parse();
260       return m_context;
261     }
262 
GetArguments()263     llvm::StringRef GetArguments() {
264       if (!m_parsed)
265         Parse();
266       return m_arguments;
267     }
268 
GetQualifiers()269     llvm::StringRef GetQualifiers() {
270       if (!m_parsed)
271         Parse();
272       return m_qualifiers;
273     }
274 
GetReturnType()275     llvm::StringRef GetReturnType() {
276       if (!m_parsed)
277         Parse();
278       return m_return_type;
279     }
280 
GetScopeQualifiedName()281     std::string GetScopeQualifiedName() {
282       if (!m_parsed)
283         Parse();
284       return m_scope_qualified;
285     }
286 
287   protected:
Parse()288     virtual void Parse() {
289       m_parsed = true;
290       m_parse_error = true;
291     }
292 
293     ConstString m_full; // Full name:
294                         // "size_t lldb::SBTarget::GetBreakpointAtIndex(unsigned
295                         // int) const"
296     llvm::StringRef m_basename;    // Basename:     "GetBreakpointAtIndex"
297     llvm::StringRef m_context;     // Decl context: "lldb::SBTarget"
298     llvm::StringRef m_arguments;   // Arguments:    "(unsigned int)"
299     llvm::StringRef m_qualifiers;  // Qualifiers:   "const"
300     llvm::StringRef m_return_type; // Return type:  "size_t"
301     std::string m_scope_qualified;
302     bool m_parsed = false;
303     bool m_parse_error = false;
304   };
305 
306   virtual std::unique_ptr<Language::MethodName>
GetMethodName(ConstString name)307   GetMethodName(ConstString name) const {
308     return std::make_unique<Language::MethodName>(name);
309   };
310 
311   virtual std::pair<lldb::FunctionNameType, std::optional<ConstString>>
GetFunctionNameInfo(ConstString name)312   GetFunctionNameInfo(ConstString name) const {
313     return std::pair{lldb::eFunctionNameTypeNone, std::nullopt};
314   };
315 
316   /// Returns true iff the given symbol name is compatible with the mangling
317   /// scheme of this language.
318   ///
319   /// This function should only return true if there is a high confidence
320   /// that the name actually belongs to this language.
SymbolNameFitsToLanguage(Mangled name)321   virtual bool SymbolNameFitsToLanguage(Mangled name) const { return false; }
322 
323   /// An individual data formatter may apply to several types and cross language
324   /// boundaries. Each of those languages may want to customize the display of
325   /// values of said types by appending proper prefix/suffix information in
326   /// language-specific ways. This function returns that prefix and suffix.
327   ///
328   /// \param[in] type_hint
329   ///   A StringRef used to determine what the prefix and suffix should be. It
330   ///   is called a hint because some types may have multiple variants for which
331   ///   the prefix and/or suffix may vary.
332   ///
333   /// \return
334   ///   A std::pair<StringRef, StringRef>, the first being the prefix and the
335   ///   second being the suffix. They may be empty.
336   virtual std::pair<llvm::StringRef, llvm::StringRef>
337   GetFormatterPrefixSuffix(llvm::StringRef type_hint);
338 
339   // When looking up functions, we take a user provided string which may be a
340   // partial match to the full demangled name and compare it to the actual
341   // demangled name to see if it matches as much as the user specified.  An
342   // example of this is if the user provided A::my_function, but the
343   // symbol was really B::A::my_function.  We want that to be
344   // a match.  But we wouldn't want this to match AnotherA::my_function.  The
345   // user is specifying a truncated path, not a truncated set of characters.
346   // This function does a language-aware comparison for those purposes.
347   virtual bool DemangledNameContainsPath(llvm::StringRef path,
348                                          ConstString demangled) const;
349 
350   // if a language has a custom format for printing variable declarations that
351   // it wants LLDB to honor it should return an appropriate closure here
352   virtual DumpValueObjectOptions::DeclPrintingHelper GetDeclPrintingHelper();
353 
354   virtual LazyBool IsLogicalTrue(ValueObject &valobj, Status &error);
355 
356   // for a ValueObject of some "reference type", if the value points to the
357   // nil/null object, this method returns true
358   virtual bool IsNilReference(ValueObject &valobj);
359 
360   /// Returns the summary string for ValueObjects for which IsNilReference() is
361   /// true.
GetNilReferenceSummaryString()362   virtual llvm::StringRef GetNilReferenceSummaryString() { return {}; }
363 
364   // for a ValueObject of some "reference type", if the language provides a
365   // technique to decide whether the reference has ever been assigned to some
366   // object, this method will return true if such detection is possible, and if
367   // the reference has never been assigned
368   virtual bool IsUninitializedReference(ValueObject &valobj);
369 
370   virtual bool GetFunctionDisplayName(const SymbolContext &sc,
371                                       const ExecutionContext *exe_ctx,
372                                       FunctionNameRepresentation representation,
373                                       Stream &s);
374 
HandleFrameFormatVariable(const SymbolContext & sc,const ExecutionContext * exe_ctx,FormatEntity::Entry::Type type,Stream & s)375   virtual bool HandleFrameFormatVariable(const SymbolContext &sc,
376                                          const ExecutionContext *exe_ctx,
377                                          FormatEntity::Entry::Type type,
378                                          Stream &s) {
379     return false;
380   }
381 
382   virtual ConstString
GetDemangledFunctionNameWithoutArguments(Mangled mangled)383   GetDemangledFunctionNameWithoutArguments(Mangled mangled) const {
384     if (ConstString demangled = mangled.GetDemangledName())
385       return demangled;
386 
387     return mangled.GetMangledName();
388   }
389 
GetDisplayDemangledName(Mangled mangled)390   virtual ConstString GetDisplayDemangledName(Mangled mangled) const {
391     return mangled.GetDemangledName();
392   }
393 
394   virtual void GetExceptionResolverDescription(bool catch_on, bool throw_on,
395                                                Stream &s);
396 
397   static void GetDefaultExceptionResolverDescription(bool catch_on,
398                                                      bool throw_on, Stream &s);
399 
400   // These are accessors for general information about the Languages lldb knows
401   // about:
402 
403   static lldb::LanguageType
404   GetLanguageTypeFromString(const char *string) = delete;
405   static lldb::LanguageType GetLanguageTypeFromString(llvm::StringRef string);
406 
407   static const char *GetNameForLanguageType(lldb::LanguageType language);
408 
409   static void PrintAllLanguages(Stream &s, const char *prefix,
410                                 const char *suffix);
411 
412   /// Prints to the specified stream 's' each language type that the
413   /// current target supports for expression evaluation.
414   ///
415   /// \param[out] s      Stream to which the language types are written.
416   /// \param[in]  prefix String that is prepended to the language type.
417   /// \param[in]  suffix String that is appended to the language type.
418   static void PrintSupportedLanguagesForExpressions(Stream &s,
419                                                     llvm::StringRef prefix,
420                                                     llvm::StringRef suffix);
421 
422   // return false from callback to stop iterating
423   static void ForAllLanguages(std::function<bool(lldb::LanguageType)> callback);
424 
425   static bool LanguageIsCPlusPlus(lldb::LanguageType language);
426 
427   static bool LanguageIsObjC(lldb::LanguageType language);
428 
429   static bool LanguageIsC(lldb::LanguageType language);
430 
431   /// Equivalent to \c LanguageIsC||LanguageIsObjC||LanguageIsCPlusPlus.
432   static bool LanguageIsCFamily(lldb::LanguageType language);
433 
434   static bool LanguageIsPascal(lldb::LanguageType language);
435 
436   // return the primary language, so if LanguageIsC(l), return eLanguageTypeC,
437   // etc.
438   static lldb::LanguageType GetPrimaryLanguage(lldb::LanguageType language);
439 
440   static std::set<lldb::LanguageType> GetSupportedLanguages();
441 
442   static LanguageSet GetLanguagesSupportingTypeSystems();
443   static LanguageSet GetLanguagesSupportingTypeSystemsForExpressions();
444   static LanguageSet GetLanguagesSupportingREPLs();
445 
446   static LanguageProperties &GetGlobalLanguageProperties();
447 
448   // Given a mangled function name, calculates some alternative manglings since
449   // the compiler mangling may not line up with the symbol we are expecting.
450   virtual std::vector<ConstString>
GenerateAlternateFunctionManglings(const ConstString mangled)451   GenerateAlternateFunctionManglings(const ConstString mangled) const {
452     return std::vector<ConstString>();
453   }
454 
455   virtual ConstString
FindBestAlternateFunctionMangledName(const Mangled mangled,const SymbolContext & sym_ctx)456   FindBestAlternateFunctionMangledName(const Mangled mangled,
457                                        const SymbolContext &sym_ctx) const {
458     return ConstString();
459   }
460 
GetInstanceVariableName()461   virtual llvm::StringRef GetInstanceVariableName() { return {}; }
462 
463   /// Given a symbol context list of matches which supposedly represent the
464   /// same file and line number in a CU, erases those that should be ignored
465   /// when setting breakpoints by line (number or regex). Helpful for languages
466   /// that create split a single source-line into many functions (e.g. call
467   /// sites transformed by CoroSplitter).
468   virtual void
FilterForLineBreakpoints(llvm::SmallVectorImpl<SymbolContext> &)469   FilterForLineBreakpoints(llvm::SmallVectorImpl<SymbolContext> &) const {}
470 
471   /// Returns a boolean indicating whether two symbol contexts are equal for the
472   /// purposes of frame comparison. If the plugin has no opinion, it should
473   /// return nullopt.
474   virtual std::optional<bool>
AreEqualForFrameComparison(const SymbolContext & sc1,const SymbolContext & sc2)475   AreEqualForFrameComparison(const SymbolContext &sc1,
476                              const SymbolContext &sc2) const {
477     return {};
478   }
479 
480   virtual std::optional<bool> GetBooleanFromString(llvm::StringRef str) const;
481 
482   /// Returns true if this Language supports exception breakpoints on throw via
483   /// a corresponding LanguageRuntime plugin.
SupportsExceptionBreakpointsOnThrow()484   virtual bool SupportsExceptionBreakpointsOnThrow() const { return false; }
485 
486   /// Returns true if this Language supports exception breakpoints on catch via
487   /// a corresponding LanguageRuntime plugin.
SupportsExceptionBreakpointsOnCatch()488   virtual bool SupportsExceptionBreakpointsOnCatch() const { return false; }
489 
490   /// Returns the keyword used for throw statements in this language, e.g.
491   /// Python uses \b raise. Defaults to \b throw.
GetThrowKeyword()492   virtual llvm::StringRef GetThrowKeyword() const { return "throw"; }
493 
494   /// Returns the keyword used for catch statements in this language, e.g.
495   /// Python uses \b except. Defaults to \b catch.
GetCatchKeyword()496   virtual llvm::StringRef GetCatchKeyword() const { return "catch"; }
497 
GetFunctionNameFormat()498   virtual FormatEntity::Entry GetFunctionNameFormat() const { return {}; }
499 
500 protected:
501   // Classes that inherit from Language can see and modify these
502 
503   Language();
504 
505 private:
506   Language(const Language &) = delete;
507   const Language &operator=(const Language &) = delete;
508 };
509 
510 } // namespace lldb_private
511 
512 #endif // LLDB_TARGET_LANGUAGE_H
513