xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- Mangled.h -----------------------------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_CORE_MANGLED_H
10 #define LLDB_CORE_MANGLED_H
11 
12 #include "lldb/Core/DemangledNameInfo.h"
13 #include "lldb/Utility/ConstString.h"
14 #include "lldb/lldb-enumerations.h"
15 #include "lldb/lldb-forward.h"
16 #include "lldb/lldb-types.h"
17 #include "llvm/ADT/StringRef.h"
18 
19 #include <cstddef>
20 #include <memory>
21 
22 namespace lldb_private {
23 
24 /// \class Mangled Mangled.h "lldb/Core/Mangled.h"
25 /// A class that handles mangled names.
26 ///
27 /// Designed to handle mangled names. The demangled version of any names will
28 /// be computed when the demangled name is accessed through the Demangled()
29 /// accessor. This class can also tokenize the demangled version of the name
30 /// for powerful searches. Functions and symbols could make instances of this
31 /// class for their mangled names. Uniqued string pools are used for the
32 /// mangled, demangled, and token string values to allow for faster
33 /// comparisons and for efficient memory use.
34 class Mangled {
35 public:
36   enum NamePreference {
37     ePreferMangled,
38     ePreferDemangled,
39     ePreferDemangledWithoutArguments
40   };
41 
42   enum ManglingScheme {
43     eManglingSchemeNone = 0,
44     eManglingSchemeMSVC,
45     eManglingSchemeItanium,
46     eManglingSchemeRustV0,
47     eManglingSchemeD,
48     eManglingSchemeSwift,
49   };
50 
51   /// Default constructor.
52   ///
53   /// Initialize with both mangled and demangled names empty.
54   Mangled() = default;
55 
56   /// Construct with name.
57   ///
58   /// Constructor with an optional string and auto-detect if \a name is
59   /// mangled or not.
60   ///
61   /// \param[in] name
62   ///     The already const name to copy into this object.
63   explicit Mangled(ConstString name);
64 
65   explicit Mangled(llvm::StringRef name);
66 
67   bool operator==(const Mangled &rhs) const {
68     return m_mangled == rhs.m_mangled &&
69            GetDemangledName() == rhs.GetDemangledName();
70   }
71 
72   bool operator!=(const Mangled &rhs) const {
73     return !(*this == rhs);
74   }
75 
76   /// Convert to bool operator.
77   ///
78   /// This allows code to check any Mangled objects to see if they contain
79   /// anything valid using code such as:
80   ///
81   /// \code
82   /// Mangled mangled(...);
83   /// if (mangled)
84   /// { ...
85   /// \endcode
86   ///
87   /// \return
88   ///     Returns \b true if either the mangled or unmangled name is set,
89   ///     \b false if the object has an empty mangled and unmangled name.
90   explicit operator bool() const;
91 
92   /// Clear the mangled and demangled values.
93   void Clear();
94 
95   /// Compare the mangled string values
96   ///
97   /// Compares the Mangled::GetName() string in \a lhs and \a rhs.
98   ///
99   /// \param[in] lhs
100   ///     A const reference to the Left Hand Side object to compare.
101   ///
102   /// \param[in] rhs
103   ///     A const reference to the Right Hand Side object to compare.
104   ///
105   /// \return
106   ///     -1 if \a lhs is less than \a rhs
107   ///     0 if \a lhs is equal to \a rhs
108   ///     1 if \a lhs is greater than \a rhs
109   static int Compare(const Mangled &lhs, const Mangled &rhs);
110 
111   /// Dump a description of this object to a Stream \a s.
112   ///
113   /// Dump a Mangled object to stream \a s. We don't force our demangled name
114   /// to be computed currently (we don't use the accessor).
115   ///
116   /// \param[in] s
117   ///     The stream to which to dump the object description.
118   void Dump(Stream *s) const;
119 
120   /// Dump a debug description of this object to a Stream \a s.
121   ///
122   /// \param[in] s
123   ///     The stream to which to dump the object description.
124   void DumpDebug(Stream *s) const;
125 
126   /// Demangled name get accessor.
127   ///
128   /// \return
129   ///     A const reference to the demangled name string object.
130   ConstString GetDemangledName() const;
131 
132   /// Display demangled name get accessor.
133   ///
134   /// \return
135   ///     A const reference to the display demangled name string object.
136   ConstString GetDisplayDemangledName() const;
137 
SetDemangledName(ConstString name)138   void SetDemangledName(ConstString name) {
139     m_demangled = name;
140     m_demangled_info.reset();
141   }
142 
SetMangledName(ConstString name)143   void SetMangledName(ConstString name) {
144     m_mangled = name;
145     m_demangled_info.reset();
146   }
147 
148   /// Mangled name get accessor.
149   ///
150   /// \return
151   ///     A reference to the mangled name string object.
GetMangledName()152   ConstString &GetMangledName() { return m_mangled; }
153 
154   /// Mangled name get accessor.
155   ///
156   /// \return
157   ///     A const reference to the mangled name string object.
GetMangledName()158   ConstString GetMangledName() const { return m_mangled; }
159 
160   /// Best name get accessor.
161   ///
162   /// \param[in] preference
163   ///     Which name would you prefer to get?
164   ///
165   /// \return
166   ///     A const reference to the preferred name string object if this
167   ///     object has a valid name of that kind, else a const reference to the
168   ///     other name is returned.
169   ConstString GetName(NamePreference preference = ePreferDemangled) const;
170 
171   /// Check if "name" matches either the mangled or demangled name.
172   ///
173   /// \param[in] name
174   ///     A name to match against both strings.
175   ///
176   /// \return
177   ///     \b True if \a name matches either name, \b false otherwise.
NameMatches(ConstString name)178   bool NameMatches(ConstString name) const {
179     if (m_mangled == name)
180       return true;
181     return GetDemangledName() == name;
182   }
183   bool NameMatches(const RegularExpression &regex) const;
184 
185   /// Get the memory cost of this object.
186   ///
187   /// Return the size in bytes that this object takes in memory. This returns
188   /// the size in bytes of this object, not any shared string values it may
189   /// refer to.
190   ///
191   /// \return
192   ///     The number of bytes that this object occupies in memory.
193   size_t MemorySize() const;
194 
195   /// Set the string value in this object.
196   ///
197   /// This version auto detects if the string is mangled by inspecting the
198   /// string value and looking for common mangling prefixes.
199   ///
200   /// \param[in] name
201   ///     The already const version of the name for this object.
202   void SetValue(ConstString name);
203 
204   /// Try to guess the language from the mangling.
205   ///
206   /// For a mangled name to have a language it must have both a mangled and a
207   /// demangled name and it can be guessed from the mangling what the language
208   /// is.  Note: this will return C++ for any language that uses Itanium ABI
209   /// mangling.
210   ///
211   /// Standard C function names will return eLanguageTypeUnknown because they
212   /// aren't mangled and it isn't clear what language the name represents
213   /// (there will be no mangled name).
214   ///
215   /// \return
216   ///     The language for the mangled/demangled name, eLanguageTypeUnknown
217   ///     if there is no mangled or demangled counterpart.
218   lldb::LanguageType GuessLanguage() const;
219 
220   /// Function signature for filtering mangled names.
221   using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
222 
223   /// Get rich mangling information. This is optimized for batch processing
224   /// while populating a name index. To get the pure demangled name string for
225   /// a single entity, use GetDemangledName() instead.
226   ///
227   /// For names that match the Itanium mangling scheme, this uses LLVM's
228   /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
229   /// parser currently.
230   ///
231   /// This function is thread-safe when used with different \a context
232   /// instances in different threads.
233   ///
234   /// \param[in] context
235   ///     The context for this function. A single instance can be stack-
236   ///     allocated in the caller's frame and used for multiple calls.
237   ///
238   /// \param[in] skip_mangled_name
239   ///     A filtering function for skipping entities based on name and mangling
240   ///     scheme. This can be null if unused.
241   ///
242   /// \return
243   ///     True on success, false otherwise.
244   bool GetRichManglingInfo(RichManglingContext &context,
245                            SkipMangledNameFn *skip_mangled_name);
246 
247   /// Try to identify the mangling scheme used.
248   /// \param[in] name
249   ///     The name we are attempting to identify the mangling scheme for.
250   ///
251   /// \return
252   ///     eManglingSchemeNone if no known mangling scheme could be identified
253   ///     for s, otherwise the enumerator for the mangling scheme detected.
254   static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
255 
256   static bool IsMangledName(llvm::StringRef name);
257 
258   /// Decode a serialized version of this object from data.
259   ///
260   /// \param data
261   ///   The decoder object that references the serialized data.
262   ///
263   /// \param offset_ptr
264   ///   A pointer that contains the offset from which the data will be decoded
265   ///   from that gets updated as data gets decoded.
266   ///
267   /// \param strtab
268   ///   All strings in cache files are put into string tables for efficiency
269   ///   and cache file size reduction. Strings are stored as uint32_t string
270   ///   table offsets in the cache data.
271   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
272               const StringTableReader &strtab);
273 
274   /// Encode this object into a data encoder object.
275   ///
276   /// This allows this object to be serialized to disk.
277   ///
278   /// \param encoder
279   ///   A data encoder object that serialized bytes will be encoded into.
280   ///
281   /// \param strtab
282   ///   All strings in cache files are put into string tables for efficiency
283   ///   and cache file size reduction. Strings are stored as uint32_t string
284   ///   table offsets in the cache data.
285   void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;
286 
287   /// Retrieve \c DemangledNameInfo of the demangled name held by this object.
288   const std::optional<DemangledNameInfo> &GetDemangledInfo() const;
289 
290 private:
291   /// If \c force is \c false, this function will re-use the previously
292   /// demangled name (if any). If \c force is \c true (or the mangled name
293   /// on this object was not previously demangled), demangle and cache the
294   /// name.
295   ConstString GetDemangledNameImpl(bool force) const;
296 
297   /// The mangled version of the name.
298   ConstString m_mangled;
299 
300   /// Mutable so we can get it on demand with
301   /// a const version of this object.
302   mutable ConstString m_demangled;
303 
304   /// If available, holds information about where in \c m_demangled certain
305   /// parts of the name (e.g., basename, arguments, etc.) begin and end.
306   mutable std::optional<DemangledNameInfo> m_demangled_info = std::nullopt;
307 };
308 
309 Stream &operator<<(Stream &s, const Mangled &obj);
310 
311 } // namespace lldb_private
312 
313 #endif // LLDB_CORE_MANGLED_H
314