aboutsummaryrefslogtreecommitdiff
path: root/source/Core/Mangled.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Mangled.cpp')
-rw-r--r--source/Core/Mangled.cpp313
1 files changed, 313 insertions, 0 deletions
diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp
new file mode 100644
index 000000000000..4655eb131a6c
--- /dev/null
+++ b/source/Core/Mangled.cpp
@@ -0,0 +1,313 @@
+//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// FreeBSD9-STABLE requires this to know about size_t in cxxabi.h
+#include <cstddef>
+#include <cxxabi.h>
+
+
+#include "llvm/ADT/DenseMap.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Mangled.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+
+using namespace lldb_private;
+
+static inline bool
+cstring_is_mangled (const char *s)
+{
+ if (s)
+ return s[0] == '_' && s[1] == 'Z';
+ return false;
+}
+
+#pragma mark Mangled
+//----------------------------------------------------------------------
+// Default constructor
+//----------------------------------------------------------------------
+Mangled::Mangled () :
+ m_mangled(),
+ m_demangled()
+{
+}
+
+//----------------------------------------------------------------------
+// Constructor with an optional string and a boolean indicating if it is
+// the mangled version.
+//----------------------------------------------------------------------
+Mangled::Mangled (const ConstString &s, bool mangled) :
+ m_mangled(),
+ m_demangled()
+{
+ if (s)
+ SetValue(s, mangled);
+}
+
+Mangled::Mangled (const ConstString &s) :
+ m_mangled(),
+ m_demangled()
+{
+ if (s)
+ SetValue(s);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+Mangled::~Mangled ()
+{
+}
+
+//----------------------------------------------------------------------
+// Convert to pointer operator. This allows code to check any Mangled
+// objects to see if they contain anything valid using code such as:
+//
+// Mangled mangled(...);
+// if (mangled)
+// { ...
+//----------------------------------------------------------------------
+Mangled::operator void* () const
+{
+ return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
+}
+
+//----------------------------------------------------------------------
+// Logical NOT operator. This allows code to check any Mangled
+// objects to see if they are invalid using code such as:
+//
+// Mangled mangled(...);
+// if (!file_spec)
+// { ...
+//----------------------------------------------------------------------
+bool
+Mangled::operator! () const
+{
+ return !m_mangled;
+}
+
+//----------------------------------------------------------------------
+// Clear the mangled and demangled values.
+//----------------------------------------------------------------------
+void
+Mangled::Clear ()
+{
+ m_mangled.Clear();
+ m_demangled.Clear();
+}
+
+
+//----------------------------------------------------------------------
+// Compare the the string values.
+//----------------------------------------------------------------------
+int
+Mangled::Compare (const Mangled& a, const Mangled& b)
+{
+ return ConstString::Compare(a.GetName(ePreferMangled), a.GetName(ePreferMangled));
+}
+
+
+
+//----------------------------------------------------------------------
+// Set the string value in this objects. If "mangled" is true, then
+// the mangled named is set with the new value in "s", else the
+// demangled name is set.
+//----------------------------------------------------------------------
+void
+Mangled::SetValue (const ConstString &s, bool mangled)
+{
+ if (s)
+ {
+ if (mangled)
+ {
+ m_demangled.Clear();
+ m_mangled = s;
+ }
+ else
+ {
+ m_demangled = s;
+ m_mangled.Clear();
+ }
+ }
+ else
+ {
+ m_demangled.Clear();
+ m_mangled.Clear();
+ }
+}
+
+void
+Mangled::SetValue (const ConstString &name)
+{
+ if (name)
+ {
+ if (cstring_is_mangled(name.GetCString()))
+ {
+ m_demangled.Clear();
+ m_mangled = name;
+ }
+ else
+ {
+ m_demangled = name;
+ m_mangled.Clear();
+ }
+ }
+ else
+ {
+ m_demangled.Clear();
+ m_mangled.Clear();
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Generate the demangled name on demand using this accessor. Code in
+// this class will need to use this accessor if it wishes to decode
+// the demangled name. The result is cached and will be kept until a
+// new string value is supplied to this object, or until the end of the
+// object's lifetime.
+//----------------------------------------------------------------------
+const ConstString&
+Mangled::GetDemangledName () const
+{
+ // Check to make sure we have a valid mangled name and that we
+ // haven't already decoded our mangled name.
+ if (m_mangled && !m_demangled)
+ {
+ // We need to generate and cache the demangled name.
+ Timer scoped_timer (__PRETTY_FUNCTION__,
+ "Mangled::GetDemangledName (m_mangled = %s)",
+ m_mangled.GetCString());
+
+ // Don't bother running anything that isn't mangled
+ const char *mangled_cstr = m_mangled.GetCString();
+ if (cstring_is_mangled(mangled_cstr))
+ {
+ if (!m_mangled.GetMangledCounterpart(m_demangled))
+ {
+ // We didn't already mangle this name, demangle it and if all goes well
+ // add it to our map.
+ char *demangled_name = abi::__cxa_demangle (mangled_cstr, NULL, NULL, NULL);
+
+ if (demangled_name)
+ {
+ m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled);
+ free (demangled_name);
+ }
+ }
+ }
+ if (!m_demangled)
+ {
+ // Set the demangled string to the empty string to indicate we
+ // tried to parse it once and failed.
+ m_demangled.SetCString("");
+ }
+ }
+
+ return m_demangled;
+}
+
+
+bool
+Mangled::NameMatches (const RegularExpression& regex) const
+{
+ if (m_mangled && regex.Execute (m_mangled.AsCString()))
+ return true;
+
+ if (GetDemangledName() && regex.Execute (m_demangled.AsCString()))
+ return true;
+ return false;
+}
+
+//----------------------------------------------------------------------
+// Get the demangled name if there is one, else return the mangled name.
+//----------------------------------------------------------------------
+const ConstString&
+Mangled::GetName (Mangled::NamePreference preference) const
+{
+ if (preference == ePreferDemangled)
+ {
+ // Call the accessor to make sure we get a demangled name in case
+ // it hasn't been demangled yet...
+ if (GetDemangledName())
+ return m_demangled;
+ return m_mangled;
+ }
+ else
+ {
+ if (m_mangled)
+ return m_mangled;
+ return GetDemangledName();
+ }
+}
+
+//----------------------------------------------------------------------
+// Dump a Mangled object to stream "s". We don't force our
+// demangled name to be computed currently (we don't use the accessor).
+//----------------------------------------------------------------------
+void
+Mangled::Dump (Stream *s) const
+{
+ if (m_mangled)
+ {
+ *s << ", mangled = " << m_mangled;
+ }
+ if (m_demangled)
+ {
+ const char * demangled = m_demangled.AsCString();
+ s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
+ }
+}
+
+//----------------------------------------------------------------------
+// Dumps a debug version of this string with extra object and state
+// information to stream "s".
+//----------------------------------------------------------------------
+void
+Mangled::DumpDebug (Stream *s) const
+{
+ s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
+ m_mangled.DumpDebug(s);
+ s->Printf(", demangled = ");
+ m_demangled.DumpDebug(s);
+}
+
+//----------------------------------------------------------------------
+// Return the size in byte that this object takes in memory. The size
+// includes the size of the objects it owns, and not the strings that
+// it references because they are shared strings.
+//----------------------------------------------------------------------
+size_t
+Mangled::MemorySize () const
+{
+ return m_mangled.MemorySize() + m_demangled.MemorySize();
+}
+
+//----------------------------------------------------------------------
+// Dump OBJ to the supplied stream S.
+//----------------------------------------------------------------------
+Stream&
+operator << (Stream& s, const Mangled& obj)
+{
+ if (obj.GetMangledName())
+ s << "mangled = '" << obj.GetMangledName() << "'";
+
+ const ConstString& demangled = obj.GetDemangledName();
+ if (demangled)
+ s << ", demangled = '" << demangled << '\'';
+ else
+ s << ", demangled = <error>";
+ return s;
+}