1254721Semaste//===-- CPPLanguageRuntime.cpp -------------------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/Target/CPPLanguageRuntime.h" 11254721Semaste 12254721Semaste#include <string.h> 13254721Semaste 14254721Semaste#include "lldb/Core/PluginManager.h" 15254721Semaste#include "lldb/Core/UniqueCStringMap.h" 16254721Semaste#include "lldb/Target/ExecutionContext.h" 17254721Semaste 18254721Semasteusing namespace lldb; 19254721Semasteusing namespace lldb_private; 20254721Semaste 21254721Semasteclass CPPRuntimeEquivalents 22254721Semaste{ 23254721Semastepublic: 24254721Semaste CPPRuntimeEquivalents () 25254721Semaste { 26254721Semaste 27254721Semaste m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>")); 28254721Semaste 29254721Semaste // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container 30254721Semaste m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>")); 31254721Semaste 32254721Semaste m_impl.Sort(); 33254721Semaste } 34254721Semaste 35254721Semaste void 36254721Semaste Add (ConstString& type_name, 37254721Semaste ConstString& type_equivalent) 38254721Semaste { 39254721Semaste m_impl.Insert(type_name.AsCString(), type_equivalent); 40254721Semaste } 41254721Semaste 42254721Semaste uint32_t 43254721Semaste FindExactMatches (ConstString& type_name, 44254721Semaste std::vector<ConstString>& equivalents) 45254721Semaste { 46254721Semaste 47254721Semaste uint32_t count = 0; 48254721Semaste 49254721Semaste for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString()); 50254721Semaste match != NULL; 51254721Semaste match = m_impl.FindNextValueForName(match)) 52254721Semaste { 53254721Semaste equivalents.push_back(match->value); 54254721Semaste count++; 55254721Semaste } 56254721Semaste 57254721Semaste return count; 58254721Semaste } 59254721Semaste 60254721Semaste // partial matches can occur when a name with equivalents is a template argument. 61254721Semaste // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename 62254721Semaste // such as "class Templatized<class Foo, Anything>" we want this to be replaced with 63254721Semaste // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming 64254721Semaste // once we get a partial match, we add it to the exact matches list for faster retrieval 65254721Semaste uint32_t 66254721Semaste FindPartialMatches (ConstString& type_name, 67254721Semaste std::vector<ConstString>& equivalents) 68254721Semaste { 69254721Semaste 70254721Semaste uint32_t count = 0; 71254721Semaste 72254721Semaste const char* type_name_cstr = type_name.AsCString(); 73254721Semaste 74254721Semaste size_t items_count = m_impl.GetSize(); 75254721Semaste 76254721Semaste for (size_t item = 0; item < items_count; item++) 77254721Semaste { 78254721Semaste const char* key_cstr = m_impl.GetCStringAtIndex(item); 79254721Semaste if ( strstr(type_name_cstr,key_cstr) ) 80254721Semaste { 81254721Semaste count += AppendReplacements(type_name_cstr, 82254721Semaste key_cstr, 83254721Semaste equivalents); 84254721Semaste } 85254721Semaste } 86254721Semaste 87254721Semaste return count; 88254721Semaste 89254721Semaste } 90254721Semaste 91254721Semasteprivate: 92254721Semaste 93254721Semaste std::string& replace (std::string& target, 94254721Semaste std::string& pattern, 95254721Semaste std::string& with) 96254721Semaste { 97254721Semaste size_t pos; 98254721Semaste size_t pattern_len = pattern.size(); 99254721Semaste 100254721Semaste while ( (pos = target.find(pattern)) != std::string::npos ) 101254721Semaste target.replace(pos, pattern_len, with); 102254721Semaste 103254721Semaste return target; 104254721Semaste } 105254721Semaste 106254721Semaste uint32_t 107254721Semaste AppendReplacements (const char* original, 108254721Semaste const char *matching_key, 109254721Semaste std::vector<ConstString>& equivalents) 110254721Semaste { 111254721Semaste 112254721Semaste std::string matching_key_str(matching_key); 113254721Semaste ConstString original_const(original); 114254721Semaste 115254721Semaste uint32_t count = 0; 116254721Semaste 117254721Semaste for (ImplData match = m_impl.FindFirstValueForName(matching_key); 118254721Semaste match != NULL; 119254721Semaste match = m_impl.FindNextValueForName(match)) 120254721Semaste { 121254721Semaste std::string target(original); 122254721Semaste std::string equiv_class(match->value.AsCString()); 123254721Semaste 124254721Semaste replace (target, matching_key_str, equiv_class); 125254721Semaste 126254721Semaste ConstString target_const(target.c_str()); 127254721Semaste 128254721Semaste// you will most probably want to leave this off since it might make this map grow indefinitely 129254721Semaste#ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW 130254721Semaste Add(original_const, target_const); 131254721Semaste#endif 132254721Semaste equivalents.push_back(target_const); 133254721Semaste 134254721Semaste count++; 135254721Semaste } 136254721Semaste 137254721Semaste return count; 138254721Semaste } 139254721Semaste 140254721Semaste typedef UniqueCStringMap<ConstString> Impl; 141254721Semaste typedef const Impl::Entry* ImplData; 142254721Semaste Impl m_impl; 143254721Semaste}; 144254721Semaste 145254721Semastestatic CPPRuntimeEquivalents& 146254721SemasteGetEquivalentsMap () 147254721Semaste{ 148254721Semaste static CPPRuntimeEquivalents g_equivalents_map; 149254721Semaste return g_equivalents_map; 150254721Semaste} 151254721Semaste 152254721Semaste//---------------------------------------------------------------------- 153254721Semaste// Destructor 154254721Semaste//---------------------------------------------------------------------- 155254721SemasteCPPLanguageRuntime::~CPPLanguageRuntime() 156254721Semaste{ 157254721Semaste} 158254721Semaste 159254721SemasteCPPLanguageRuntime::CPPLanguageRuntime (Process *process) : 160254721Semaste LanguageRuntime (process) 161254721Semaste{ 162254721Semaste 163254721Semaste} 164254721Semaste 165254721Semastebool 166254721SemasteCPPLanguageRuntime::GetObjectDescription (Stream &str, ValueObject &object) 167254721Semaste{ 168254721Semaste // C++ has no generic way to do this. 169254721Semaste return false; 170254721Semaste} 171254721Semaste 172254721Semastebool 173254721SemasteCPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) 174254721Semaste{ 175254721Semaste // C++ has no generic way to do this. 176254721Semaste return false; 177254721Semaste} 178254721Semaste 179254721Semastebool 180254721SemasteCPPLanguageRuntime::IsCPPMangledName (const char *name) 181254721Semaste{ 182254721Semaste // FIXME, we should really run through all the known C++ Language plugins and ask each one if 183254721Semaste // this is a C++ mangled name, but we can put that off till there is actually more than one 184254721Semaste // we care about. 185254721Semaste 186254721Semaste if (name && name[0] == '_' && name[1] == 'Z') 187254721Semaste return true; 188254721Semaste else 189254721Semaste return false; 190254721Semaste} 191254721Semaste 192254721Semastebool 193254721SemasteCPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end) 194254721Semaste{ 195254721Semaste if (base_name_end == NULL) 196254721Semaste base_name_end = name + strlen (name); 197254721Semaste 198254721Semaste const char *last_colon = strrchr (name, ':'); 199254721Semaste 200254721Semaste if (last_colon == NULL) 201254721Semaste { 202254721Semaste base_name_start = name; 203254721Semaste return true; 204254721Semaste } 205254721Semaste 206254721Semaste // Can't have a C++ name that begins with a single ':', nor contains an internal single ':' 207254721Semaste if (last_colon == name) 208254721Semaste return false; 209254721Semaste else if (last_colon[-1] != ':') 210254721Semaste return false; 211254721Semaste else 212254721Semaste { 213254721Semaste // FIXME: should check if there is 214254721Semaste base_name_start = last_colon + 1; 215254721Semaste return true; 216254721Semaste } 217254721Semaste} 218254721Semaste 219254721Semasteuint32_t 220254721SemasteCPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents) 221254721Semaste{ 222254721Semaste uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents); 223254721Semaste 224254721Semaste bool might_have_partials= 225254721Semaste ( count == 0 ) // if we have a full name match just use it 226254721Semaste && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have 227254721Semaste && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches 228254721Semaste 229254721Semaste if ( might_have_partials ) 230254721Semaste count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); 231254721Semaste 232254721Semaste return count; 233254721Semaste} 234254721Semaste 235254721Semastevoid 236254721SemasteCPPLanguageRuntime::MethodName::Clear() 237254721Semaste{ 238254721Semaste m_full.Clear(); 239254721Semaste m_basename = llvm::StringRef(); 240254721Semaste m_context = llvm::StringRef(); 241254721Semaste m_arguments = llvm::StringRef(); 242254721Semaste m_qualifiers = llvm::StringRef(); 243254721Semaste m_type = eTypeInvalid; 244254721Semaste m_parsed = false; 245254721Semaste m_parse_error = false; 246254721Semaste} 247254721Semaste 248254721Semastebool 249254721SemasteReverseFindMatchingChars (const llvm::StringRef &s, 250254721Semaste const llvm::StringRef &left_right_chars, 251254721Semaste size_t &left_pos, 252254721Semaste size_t &right_pos, 253254721Semaste size_t pos = llvm::StringRef::npos) 254254721Semaste{ 255254721Semaste assert (left_right_chars.size() == 2); 256254721Semaste left_pos = llvm::StringRef::npos; 257254721Semaste const char left_char = left_right_chars[0]; 258254721Semaste const char right_char = left_right_chars[1]; 259254721Semaste pos = s.find_last_of(left_right_chars, pos); 260254721Semaste if (pos == llvm::StringRef::npos || s[pos] == left_char) 261254721Semaste return false; 262254721Semaste right_pos = pos; 263254721Semaste uint32_t depth = 1; 264254721Semaste while (pos > 0 && depth > 0) 265254721Semaste { 266254721Semaste pos = s.find_last_of(left_right_chars, pos); 267254721Semaste if (pos == llvm::StringRef::npos) 268254721Semaste return false; 269254721Semaste if (s[pos] == left_char) 270254721Semaste { 271254721Semaste if (--depth == 0) 272254721Semaste { 273254721Semaste left_pos = pos; 274254721Semaste return left_pos < right_pos; 275254721Semaste } 276254721Semaste } 277254721Semaste else if (s[pos] == right_char) 278254721Semaste { 279254721Semaste ++depth; 280254721Semaste } 281254721Semaste } 282254721Semaste return false; 283254721Semaste} 284254721Semaste 285254721Semastevoid 286254721SemasteCPPLanguageRuntime::MethodName::Parse() 287254721Semaste{ 288254721Semaste if (!m_parsed && m_full) 289254721Semaste { 290254721Semaste// ConstString mangled; 291254721Semaste// m_full.GetMangledCounterpart(mangled); 292254721Semaste// printf ("\n parsing = '%s'\n", m_full.GetCString()); 293254721Semaste// if (mangled) 294254721Semaste// printf (" mangled = '%s'\n", mangled.GetCString()); 295254721Semaste m_parse_error = false; 296254721Semaste m_parsed = true; 297254721Semaste llvm::StringRef full (m_full.GetCString()); 298254721Semaste 299254721Semaste size_t arg_start, arg_end; 300254721Semaste llvm::StringRef parens("()", 2); 301254721Semaste if (ReverseFindMatchingChars (full, parens, arg_start, arg_end)) 302254721Semaste { 303254721Semaste m_arguments = full.substr(arg_start, arg_end - arg_start + 1); 304254721Semaste if (arg_end + 1 < full.size()) 305254721Semaste m_qualifiers = full.substr(arg_end + 1); 306254721Semaste if (arg_start > 0) 307254721Semaste { 308254721Semaste size_t basename_end = arg_start; 309254721Semaste size_t context_end = llvm::StringRef::npos; 310254721Semaste if (basename_end > 0 && full[basename_end-1] == '>') 311254721Semaste { 312254721Semaste // TODO: handle template junk... 313254721Semaste // Templated function 314254721Semaste size_t template_start, template_end; 315254721Semaste llvm::StringRef lt_gt("<>", 2); 316254721Semaste if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end)) 317254721Semaste context_end = full.rfind(':', template_start); 318254721Semaste } 319254721Semaste if (context_end == llvm::StringRef::npos) 320254721Semaste context_end = full.rfind(':', basename_end); 321254721Semaste 322254721Semaste if (context_end == llvm::StringRef::npos) 323254721Semaste m_basename = full.substr(0, basename_end); 324254721Semaste else 325254721Semaste { 326254721Semaste m_context = full.substr(0, context_end - 1); 327254721Semaste const size_t basename_begin = context_end + 1; 328254721Semaste m_basename = full.substr(basename_begin, basename_end - basename_begin); 329254721Semaste } 330254721Semaste m_type = eTypeUnknownMethod; 331254721Semaste } 332254721Semaste else 333254721Semaste { 334254721Semaste m_parse_error = true; 335254721Semaste return; 336254721Semaste } 337254721Semaste 338254721Semaste// if (!m_context.empty()) 339254721Semaste// printf (" context = '%s'\n", m_context.str().c_str()); 340254721Semaste// if (m_basename) 341254721Semaste// printf (" basename = '%s'\n", m_basename.GetCString()); 342254721Semaste// if (!m_arguments.empty()) 343254721Semaste// printf (" arguments = '%s'\n", m_arguments.str().c_str()); 344254721Semaste// if (!m_qualifiers.empty()) 345254721Semaste// printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str()); 346254721Semaste } 347254721Semaste else 348254721Semaste { 349254721Semaste m_parse_error = true; 350254721Semaste// printf ("error: didn't find matching parens for arguments\n"); 351254721Semaste } 352254721Semaste } 353254721Semaste} 354254721Semaste 355254721Semastellvm::StringRef 356254721SemasteCPPLanguageRuntime::MethodName::GetBasename () 357254721Semaste{ 358254721Semaste if (!m_parsed) 359254721Semaste Parse(); 360254721Semaste return m_basename; 361254721Semaste} 362254721Semaste 363254721Semastellvm::StringRef 364254721SemasteCPPLanguageRuntime::MethodName::GetContext () 365254721Semaste{ 366254721Semaste if (!m_parsed) 367254721Semaste Parse(); 368254721Semaste return m_context; 369254721Semaste} 370254721Semaste 371254721Semastellvm::StringRef 372254721SemasteCPPLanguageRuntime::MethodName::GetArguments () 373254721Semaste{ 374254721Semaste if (!m_parsed) 375254721Semaste Parse(); 376254721Semaste return m_arguments; 377254721Semaste} 378254721Semaste 379254721Semastellvm::StringRef 380254721SemasteCPPLanguageRuntime::MethodName::GetQualifiers () 381254721Semaste{ 382254721Semaste if (!m_parsed) 383254721Semaste Parse(); 384254721Semaste return m_qualifiers; 385254721Semaste} 386254721Semaste 387