10b57cec5SDimitry Andric //===-- Mangled.h -----------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_CORE_MANGLED_H
105ffd83dbSDimitry Andric #define LLDB_CORE_MANGLED_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "lldb/lldb-enumerations.h"
130b57cec5SDimitry Andric #include "lldb/lldb-forward.h"
140eae32dcSDimitry Andric #include "lldb/lldb-types.h"
150b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
160b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
170b57cec5SDimitry Andric 
18fe6060f1SDimitry Andric #include <cstddef>
190b57cec5SDimitry Andric #include <memory>
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric namespace lldb_private {
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric /// \class Mangled Mangled.h "lldb/Core/Mangled.h"
240b57cec5SDimitry Andric /// A class that handles mangled names.
250b57cec5SDimitry Andric ///
260b57cec5SDimitry Andric /// Designed to handle mangled names. The demangled version of any names will
270b57cec5SDimitry Andric /// be computed when the demangled name is accessed through the Demangled()
28bdd1243dSDimitry Andric /// accessor. This class can also tokenize the demangled version of the name
290b57cec5SDimitry Andric /// for powerful searches. Functions and symbols could make instances of this
300b57cec5SDimitry Andric /// class for their mangled names. Uniqued string pools are used for the
310b57cec5SDimitry Andric /// mangled, demangled, and token string values to allow for faster
320b57cec5SDimitry Andric /// comparisons and for efficient memory use.
330b57cec5SDimitry Andric class Mangled {
340b57cec5SDimitry Andric public:
350b57cec5SDimitry Andric   enum NamePreference {
360b57cec5SDimitry Andric     ePreferMangled,
370b57cec5SDimitry Andric     ePreferDemangled,
380b57cec5SDimitry Andric     ePreferDemangledWithoutArguments
390b57cec5SDimitry Andric   };
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   enum ManglingScheme {
420b57cec5SDimitry Andric     eManglingSchemeNone = 0,
430b57cec5SDimitry Andric     eManglingSchemeMSVC,
44fe6060f1SDimitry Andric     eManglingSchemeItanium,
45349cc55cSDimitry Andric     eManglingSchemeRustV0,
465f757f3fSDimitry Andric     eManglingSchemeD,
475f757f3fSDimitry Andric     eManglingSchemeSwift,
480b57cec5SDimitry Andric   };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// Default constructor.
510b57cec5SDimitry Andric   ///
520b57cec5SDimitry Andric   /// Initialize with both mangled and demangled names empty.
539dba64beSDimitry Andric   Mangled() = default;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   /// Construct with name.
560b57cec5SDimitry Andric   ///
570b57cec5SDimitry Andric   /// Constructor with an optional string and auto-detect if \a name is
580b57cec5SDimitry Andric   /// mangled or not.
590b57cec5SDimitry Andric   ///
600b57cec5SDimitry Andric   /// \param[in] name
610b57cec5SDimitry Andric   ///     The already const name to copy into this object.
620b57cec5SDimitry Andric   explicit Mangled(ConstString name);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   explicit Mangled(llvm::StringRef name);
650b57cec5SDimitry Andric 
660eae32dcSDimitry Andric   bool operator==(const Mangled &rhs) const {
670eae32dcSDimitry Andric     return m_mangled == rhs.m_mangled &&
680eae32dcSDimitry Andric            GetDemangledName() == rhs.GetDemangledName();
690eae32dcSDimitry Andric   }
700eae32dcSDimitry Andric 
710eae32dcSDimitry Andric   bool operator!=(const Mangled &rhs) const {
720eae32dcSDimitry Andric     return !(*this == rhs);
730eae32dcSDimitry Andric   }
740eae32dcSDimitry Andric 
7504eeddc0SDimitry Andric   /// Convert to bool operator.
760b57cec5SDimitry Andric   ///
7704eeddc0SDimitry Andric   /// This allows code to check any Mangled objects to see if they contain
7804eeddc0SDimitry Andric   /// anything valid using code such as:
790b57cec5SDimitry Andric   ///
800b57cec5SDimitry Andric   /// \code
810b57cec5SDimitry Andric   /// Mangled mangled(...);
820b57cec5SDimitry Andric   /// if (mangled)
830b57cec5SDimitry Andric   /// { ...
840b57cec5SDimitry Andric   /// \endcode
850b57cec5SDimitry Andric   ///
860b57cec5SDimitry Andric   /// \return
8704eeddc0SDimitry Andric   ///     Returns \b true if either the mangled or unmangled name is set,
8804eeddc0SDimitry Andric   ///     \b false if the object has an empty mangled and unmangled name.
8904eeddc0SDimitry Andric   explicit operator bool() const;
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Clear the mangled and demangled values.
920b57cec5SDimitry Andric   void Clear();
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   /// Compare the mangled string values
950b57cec5SDimitry Andric   ///
960b57cec5SDimitry Andric   /// Compares the Mangled::GetName() string in \a lhs and \a rhs.
970b57cec5SDimitry Andric   ///
980b57cec5SDimitry Andric   /// \param[in] lhs
990b57cec5SDimitry Andric   ///     A const reference to the Left Hand Side object to compare.
1000b57cec5SDimitry Andric   ///
1010b57cec5SDimitry Andric   /// \param[in] rhs
1020b57cec5SDimitry Andric   ///     A const reference to the Right Hand Side object to compare.
1030b57cec5SDimitry Andric   ///
1040b57cec5SDimitry Andric   /// \return
105480093f4SDimitry Andric   ///     -1 if \a lhs is less than \a rhs
106480093f4SDimitry Andric   ///     0 if \a lhs is equal to \a rhs
107480093f4SDimitry Andric   ///     1 if \a lhs is greater than \a rhs
1080b57cec5SDimitry Andric   static int Compare(const Mangled &lhs, const Mangled &rhs);
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   /// Dump a description of this object to a Stream \a s.
1110b57cec5SDimitry Andric   ///
1120b57cec5SDimitry Andric   /// Dump a Mangled object to stream \a s. We don't force our demangled name
1130b57cec5SDimitry Andric   /// to be computed currently (we don't use the accessor).
1140b57cec5SDimitry Andric   ///
1150b57cec5SDimitry Andric   /// \param[in] s
1160b57cec5SDimitry Andric   ///     The stream to which to dump the object description.
1170b57cec5SDimitry Andric   void Dump(Stream *s) const;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   /// Dump a debug description of this object to a Stream \a s.
1200b57cec5SDimitry Andric   ///
1210b57cec5SDimitry Andric   /// \param[in] s
1220b57cec5SDimitry Andric   ///     The stream to which to dump the object description.
1230b57cec5SDimitry Andric   void DumpDebug(Stream *s) const;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   /// Demangled name get accessor.
1260b57cec5SDimitry Andric   ///
1270b57cec5SDimitry Andric   /// \return
1280b57cec5SDimitry Andric   ///     A const reference to the demangled name string object.
1295ffd83dbSDimitry Andric   ConstString GetDemangledName() const;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   /// Display demangled name get accessor.
1320b57cec5SDimitry Andric   ///
1330b57cec5SDimitry Andric   /// \return
1340b57cec5SDimitry Andric   ///     A const reference to the display demangled name string object.
1355ffd83dbSDimitry Andric   ConstString GetDisplayDemangledName() const;
1360b57cec5SDimitry Andric 
SetDemangledName(ConstString name)1370b57cec5SDimitry Andric   void SetDemangledName(ConstString name) { m_demangled = name; }
1380b57cec5SDimitry Andric 
SetMangledName(ConstString name)1390b57cec5SDimitry Andric   void SetMangledName(ConstString name) { m_mangled = name; }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   /// Mangled name get accessor.
1420b57cec5SDimitry Andric   ///
1430b57cec5SDimitry Andric   /// \return
1440b57cec5SDimitry Andric   ///     A reference to the mangled name string object.
GetMangledName()1450b57cec5SDimitry Andric   ConstString &GetMangledName() { return m_mangled; }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   /// Mangled name get accessor.
1480b57cec5SDimitry Andric   ///
1490b57cec5SDimitry Andric   /// \return
1500b57cec5SDimitry Andric   ///     A const reference to the mangled name string object.
GetMangledName()1510b57cec5SDimitry Andric   ConstString GetMangledName() const { return m_mangled; }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   /// Best name get accessor.
1540b57cec5SDimitry Andric   ///
1550b57cec5SDimitry Andric   /// \param[in] preference
1560b57cec5SDimitry Andric   ///     Which name would you prefer to get?
1570b57cec5SDimitry Andric   ///
1580b57cec5SDimitry Andric   /// \return
1590b57cec5SDimitry Andric   ///     A const reference to the preferred name string object if this
1600b57cec5SDimitry Andric   ///     object has a valid name of that kind, else a const reference to the
1610b57cec5SDimitry Andric   ///     other name is returned.
1625ffd83dbSDimitry Andric   ConstString GetName(NamePreference preference = ePreferDemangled) const;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   /// Check if "name" matches either the mangled or demangled name.
1650b57cec5SDimitry Andric   ///
1660b57cec5SDimitry Andric   /// \param[in] name
1670b57cec5SDimitry Andric   ///     A name to match against both strings.
1680b57cec5SDimitry Andric   ///
1690b57cec5SDimitry Andric   /// \return
1700b57cec5SDimitry Andric   ///     \b True if \a name matches either name, \b false otherwise.
NameMatches(ConstString name)1715ffd83dbSDimitry Andric   bool NameMatches(ConstString name) const {
1720b57cec5SDimitry Andric     if (m_mangled == name)
1730b57cec5SDimitry Andric       return true;
1745ffd83dbSDimitry Andric     return GetDemangledName() == name;
1750b57cec5SDimitry Andric   }
1765ffd83dbSDimitry Andric   bool NameMatches(const RegularExpression &regex) const;
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric   /// Get the memory cost of this object.
1790b57cec5SDimitry Andric   ///
1800b57cec5SDimitry Andric   /// Return the size in bytes that this object takes in memory. This returns
1810b57cec5SDimitry Andric   /// the size in bytes of this object, not any shared string values it may
1820b57cec5SDimitry Andric   /// refer to.
1830b57cec5SDimitry Andric   ///
1840b57cec5SDimitry Andric   /// \return
1850b57cec5SDimitry Andric   ///     The number of bytes that this object occupies in memory.
1860b57cec5SDimitry Andric   size_t MemorySize() const;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   /// Set the string value in this object.
1890b57cec5SDimitry Andric   ///
1900b57cec5SDimitry Andric   /// This version auto detects if the string is mangled by inspecting the
1910b57cec5SDimitry Andric   /// string value and looking for common mangling prefixes.
1920b57cec5SDimitry Andric   ///
1930b57cec5SDimitry Andric   /// \param[in] name
1940b57cec5SDimitry Andric   ///     The already const version of the name for this object.
1950b57cec5SDimitry Andric   void SetValue(ConstString name);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   /// Try to guess the language from the mangling.
1980b57cec5SDimitry Andric   ///
1990b57cec5SDimitry Andric   /// For a mangled name to have a language it must have both a mangled and a
2000b57cec5SDimitry Andric   /// demangled name and it can be guessed from the mangling what the language
2010b57cec5SDimitry Andric   /// is.  Note: this will return C++ for any language that uses Itanium ABI
2020b57cec5SDimitry Andric   /// mangling.
2030b57cec5SDimitry Andric   ///
2040b57cec5SDimitry Andric   /// Standard C function names will return eLanguageTypeUnknown because they
2050b57cec5SDimitry Andric   /// aren't mangled and it isn't clear what language the name represents
2060b57cec5SDimitry Andric   /// (there will be no mangled name).
2070b57cec5SDimitry Andric   ///
2080b57cec5SDimitry Andric   /// \return
2090b57cec5SDimitry Andric   ///     The language for the mangled/demangled name, eLanguageTypeUnknown
2100b57cec5SDimitry Andric   ///     if there is no mangled or demangled counterpart.
2110b57cec5SDimitry Andric   lldb::LanguageType GuessLanguage() const;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   /// Function signature for filtering mangled names.
2140b57cec5SDimitry Andric   using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme);
2150b57cec5SDimitry Andric 
216d56accc7SDimitry Andric   /// Get rich mangling information. This is optimized for batch processing
217d56accc7SDimitry Andric   /// while populating a name index. To get the pure demangled name string for
218d56accc7SDimitry Andric   /// a single entity, use GetDemangledName() instead.
2190b57cec5SDimitry Andric   ///
2200b57cec5SDimitry Andric   /// For names that match the Itanium mangling scheme, this uses LLVM's
2210b57cec5SDimitry Andric   /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin
2220b57cec5SDimitry Andric   /// parser currently.
2230b57cec5SDimitry Andric   ///
2240b57cec5SDimitry Andric   /// This function is thread-safe when used with different \a context
2250b57cec5SDimitry Andric   /// instances in different threads.
2260b57cec5SDimitry Andric   ///
2270b57cec5SDimitry Andric   /// \param[in] context
2280b57cec5SDimitry Andric   ///     The context for this function. A single instance can be stack-
2290b57cec5SDimitry Andric   ///     allocated in the caller's frame and used for multiple calls.
2300b57cec5SDimitry Andric   ///
2310b57cec5SDimitry Andric   /// \param[in] skip_mangled_name
2320b57cec5SDimitry Andric   ///     A filtering function for skipping entities based on name and mangling
2330b57cec5SDimitry Andric   ///     scheme. This can be null if unused.
2340b57cec5SDimitry Andric   ///
2350b57cec5SDimitry Andric   /// \return
2360b57cec5SDimitry Andric   ///     True on success, false otherwise.
237d56accc7SDimitry Andric   bool GetRichManglingInfo(RichManglingContext &context,
2380b57cec5SDimitry Andric                            SkipMangledNameFn *skip_mangled_name);
2390b57cec5SDimitry Andric 
240480093f4SDimitry Andric   /// Try to identify the mangling scheme used.
241480093f4SDimitry Andric   /// \param[in] name
242480093f4SDimitry Andric   ///     The name we are attempting to identify the mangling scheme for.
243480093f4SDimitry Andric   ///
244480093f4SDimitry Andric   /// \return
245480093f4SDimitry Andric   ///     eManglingSchemeNone if no known mangling scheme could be identified
246480093f4SDimitry Andric   ///     for s, otherwise the enumerator for the mangling scheme detected.
247480093f4SDimitry Andric   static Mangled::ManglingScheme GetManglingScheme(llvm::StringRef const name);
248480093f4SDimitry Andric 
2490eae32dcSDimitry Andric   /// Decode a serialized version of this object from data.
2500eae32dcSDimitry Andric   ///
2510eae32dcSDimitry Andric   /// \param data
2520eae32dcSDimitry Andric   ///   The decoder object that references the serialized data.
2530eae32dcSDimitry Andric   ///
2540eae32dcSDimitry Andric   /// \param offset_ptr
2550eae32dcSDimitry Andric   ///   A pointer that contains the offset from which the data will be decoded
2560eae32dcSDimitry Andric   ///   from that gets updated as data gets decoded.
2570eae32dcSDimitry Andric   ///
2580eae32dcSDimitry Andric   /// \param strtab
2590eae32dcSDimitry Andric   ///   All strings in cache files are put into string tables for efficiency
2600eae32dcSDimitry Andric   ///   and cache file size reduction. Strings are stored as uint32_t string
2610eae32dcSDimitry Andric   ///   table offsets in the cache data.
2620eae32dcSDimitry Andric   bool Decode(const DataExtractor &data, lldb::offset_t *offset_ptr,
2630eae32dcSDimitry Andric               const StringTableReader &strtab);
2640eae32dcSDimitry Andric 
2650eae32dcSDimitry Andric   /// Encode this object into a data encoder object.
2660eae32dcSDimitry Andric   ///
2670eae32dcSDimitry Andric   /// This allows this object to be serialized to disk.
2680eae32dcSDimitry Andric   ///
2690eae32dcSDimitry Andric   /// \param encoder
2700eae32dcSDimitry Andric   ///   A data encoder object that serialized bytes will be encoded into.
2710eae32dcSDimitry Andric   ///
2720eae32dcSDimitry Andric   /// \param strtab
2730eae32dcSDimitry Andric   ///   All strings in cache files are put into string tables for efficiency
2740eae32dcSDimitry Andric   ///   and cache file size reduction. Strings are stored as uint32_t string
2750eae32dcSDimitry Andric   ///   table offsets in the cache data.
2760eae32dcSDimitry Andric   void Encode(DataEncoder &encoder, ConstStringTable &strtab) const;
2770eae32dcSDimitry Andric 
2780b57cec5SDimitry Andric private:
2790b57cec5SDimitry Andric   /// Mangled member variables.
2800b57cec5SDimitry Andric   ConstString m_mangled;           ///< The mangled version of the name
2810b57cec5SDimitry Andric   mutable ConstString m_demangled; ///< Mutable so we can get it on demand with
2820b57cec5SDimitry Andric                                    ///a const version of this object
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric Stream &operator<<(Stream &s, const Mangled &obj);
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric } // namespace lldb_private
2880b57cec5SDimitry Andric 
2895ffd83dbSDimitry Andric #endif // LLDB_CORE_MANGLED_H
290