1ac7ddfbfSEd Maste //===-- CPPLanguageRuntime.cpp -------------------------------------------------*- C++ -*-===// 2ac7ddfbfSEd Maste // 3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure 4ac7ddfbfSEd Maste // 5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source 6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details. 7ac7ddfbfSEd Maste // 8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===// 9ac7ddfbfSEd Maste 10ac7ddfbfSEd Maste #include "lldb/Target/CPPLanguageRuntime.h" 11ac7ddfbfSEd Maste 12ac7ddfbfSEd Maste #include <string.h> 13ac7ddfbfSEd Maste 14ac7ddfbfSEd Maste #include "lldb/Core/PluginManager.h" 15ac7ddfbfSEd Maste #include "lldb/Core/UniqueCStringMap.h" 16ac7ddfbfSEd Maste #include "lldb/Target/ExecutionContext.h" 17ac7ddfbfSEd Maste 18ac7ddfbfSEd Maste using namespace lldb; 19ac7ddfbfSEd Maste using namespace lldb_private; 20ac7ddfbfSEd Maste 21ac7ddfbfSEd Maste class CPPRuntimeEquivalents 22ac7ddfbfSEd Maste { 23ac7ddfbfSEd Maste public: 24ac7ddfbfSEd Maste CPPRuntimeEquivalents () 25ac7ddfbfSEd Maste { 26ac7ddfbfSEd Maste 27ac7ddfbfSEd Maste m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("basic_string<char>")); 28ac7ddfbfSEd Maste 29ac7ddfbfSEd Maste // these two (with a prefixed std::) occur when c++stdlib string class occurs as a template argument in some STL container 30ac7ddfbfSEd Maste m_impl.Append(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >").AsCString(), ConstString("std::basic_string<char>")); 31ac7ddfbfSEd Maste 32ac7ddfbfSEd Maste m_impl.Sort(); 33ac7ddfbfSEd Maste } 34ac7ddfbfSEd Maste 35ac7ddfbfSEd Maste void 36ac7ddfbfSEd Maste Add (ConstString& type_name, 37ac7ddfbfSEd Maste ConstString& type_equivalent) 38ac7ddfbfSEd Maste { 39ac7ddfbfSEd Maste m_impl.Insert(type_name.AsCString(), type_equivalent); 40ac7ddfbfSEd Maste } 41ac7ddfbfSEd Maste 42ac7ddfbfSEd Maste uint32_t 43ac7ddfbfSEd Maste FindExactMatches (ConstString& type_name, 44ac7ddfbfSEd Maste std::vector<ConstString>& equivalents) 45ac7ddfbfSEd Maste { 46ac7ddfbfSEd Maste 47ac7ddfbfSEd Maste uint32_t count = 0; 48ac7ddfbfSEd Maste 49ac7ddfbfSEd Maste for (ImplData match = m_impl.FindFirstValueForName(type_name.AsCString()); 50ac7ddfbfSEd Maste match != NULL; 51ac7ddfbfSEd Maste match = m_impl.FindNextValueForName(match)) 52ac7ddfbfSEd Maste { 53ac7ddfbfSEd Maste equivalents.push_back(match->value); 54ac7ddfbfSEd Maste count++; 55ac7ddfbfSEd Maste } 56ac7ddfbfSEd Maste 57ac7ddfbfSEd Maste return count; 58ac7ddfbfSEd Maste } 59ac7ddfbfSEd Maste 60ac7ddfbfSEd Maste // partial matches can occur when a name with equivalents is a template argument. 61ac7ddfbfSEd Maste // e.g. we may have "class Foo" be a match for "struct Bar". if we have a typename 62ac7ddfbfSEd Maste // such as "class Templatized<class Foo, Anything>" we want this to be replaced with 63ac7ddfbfSEd Maste // "class Templatized<struct Bar, Anything>". Since partial matching is time consuming 64ac7ddfbfSEd Maste // once we get a partial match, we add it to the exact matches list for faster retrieval 65ac7ddfbfSEd Maste uint32_t 66ac7ddfbfSEd Maste FindPartialMatches (ConstString& type_name, 67ac7ddfbfSEd Maste std::vector<ConstString>& equivalents) 68ac7ddfbfSEd Maste { 69ac7ddfbfSEd Maste 70ac7ddfbfSEd Maste uint32_t count = 0; 71ac7ddfbfSEd Maste 72ac7ddfbfSEd Maste const char* type_name_cstr = type_name.AsCString(); 73ac7ddfbfSEd Maste 74ac7ddfbfSEd Maste size_t items_count = m_impl.GetSize(); 75ac7ddfbfSEd Maste 76ac7ddfbfSEd Maste for (size_t item = 0; item < items_count; item++) 77ac7ddfbfSEd Maste { 78ac7ddfbfSEd Maste const char* key_cstr = m_impl.GetCStringAtIndex(item); 79ac7ddfbfSEd Maste if ( strstr(type_name_cstr,key_cstr) ) 80ac7ddfbfSEd Maste { 81ac7ddfbfSEd Maste count += AppendReplacements(type_name_cstr, 82ac7ddfbfSEd Maste key_cstr, 83ac7ddfbfSEd Maste equivalents); 84ac7ddfbfSEd Maste } 85ac7ddfbfSEd Maste } 86ac7ddfbfSEd Maste 87ac7ddfbfSEd Maste return count; 88ac7ddfbfSEd Maste 89ac7ddfbfSEd Maste } 90ac7ddfbfSEd Maste 91ac7ddfbfSEd Maste private: 92ac7ddfbfSEd Maste 93ac7ddfbfSEd Maste std::string& replace (std::string& target, 94ac7ddfbfSEd Maste std::string& pattern, 95ac7ddfbfSEd Maste std::string& with) 96ac7ddfbfSEd Maste { 97ac7ddfbfSEd Maste size_t pos; 98ac7ddfbfSEd Maste size_t pattern_len = pattern.size(); 99ac7ddfbfSEd Maste 100ac7ddfbfSEd Maste while ( (pos = target.find(pattern)) != std::string::npos ) 101ac7ddfbfSEd Maste target.replace(pos, pattern_len, with); 102ac7ddfbfSEd Maste 103ac7ddfbfSEd Maste return target; 104ac7ddfbfSEd Maste } 105ac7ddfbfSEd Maste 106ac7ddfbfSEd Maste uint32_t 107ac7ddfbfSEd Maste AppendReplacements (const char* original, 108ac7ddfbfSEd Maste const char *matching_key, 109ac7ddfbfSEd Maste std::vector<ConstString>& equivalents) 110ac7ddfbfSEd Maste { 111ac7ddfbfSEd Maste 112ac7ddfbfSEd Maste std::string matching_key_str(matching_key); 113ac7ddfbfSEd Maste ConstString original_const(original); 114ac7ddfbfSEd Maste 115ac7ddfbfSEd Maste uint32_t count = 0; 116ac7ddfbfSEd Maste 117ac7ddfbfSEd Maste for (ImplData match = m_impl.FindFirstValueForName(matching_key); 118ac7ddfbfSEd Maste match != NULL; 119ac7ddfbfSEd Maste match = m_impl.FindNextValueForName(match)) 120ac7ddfbfSEd Maste { 121ac7ddfbfSEd Maste std::string target(original); 122ac7ddfbfSEd Maste std::string equiv_class(match->value.AsCString()); 123ac7ddfbfSEd Maste 124ac7ddfbfSEd Maste replace (target, matching_key_str, equiv_class); 125ac7ddfbfSEd Maste 126ac7ddfbfSEd Maste ConstString target_const(target.c_str()); 127ac7ddfbfSEd Maste 128ac7ddfbfSEd Maste // you will most probably want to leave this off since it might make this map grow indefinitely 129ac7ddfbfSEd Maste #ifdef ENABLE_CPP_EQUIVALENTS_MAP_TO_GROW 130ac7ddfbfSEd Maste Add(original_const, target_const); 131ac7ddfbfSEd Maste #endif 132ac7ddfbfSEd Maste equivalents.push_back(target_const); 133ac7ddfbfSEd Maste 134ac7ddfbfSEd Maste count++; 135ac7ddfbfSEd Maste } 136ac7ddfbfSEd Maste 137ac7ddfbfSEd Maste return count; 138ac7ddfbfSEd Maste } 139ac7ddfbfSEd Maste 140ac7ddfbfSEd Maste typedef UniqueCStringMap<ConstString> Impl; 141ac7ddfbfSEd Maste typedef const Impl::Entry* ImplData; 142ac7ddfbfSEd Maste Impl m_impl; 143ac7ddfbfSEd Maste }; 144ac7ddfbfSEd Maste 145ac7ddfbfSEd Maste static CPPRuntimeEquivalents& 146ac7ddfbfSEd Maste GetEquivalentsMap () 147ac7ddfbfSEd Maste { 148ac7ddfbfSEd Maste static CPPRuntimeEquivalents g_equivalents_map; 149ac7ddfbfSEd Maste return g_equivalents_map; 150ac7ddfbfSEd Maste } 151ac7ddfbfSEd Maste 152ac7ddfbfSEd Maste //---------------------------------------------------------------------- 153ac7ddfbfSEd Maste // Destructor 154ac7ddfbfSEd Maste //---------------------------------------------------------------------- 155ac7ddfbfSEd Maste CPPLanguageRuntime::~CPPLanguageRuntime() 156ac7ddfbfSEd Maste { 157ac7ddfbfSEd Maste } 158ac7ddfbfSEd Maste 159ac7ddfbfSEd Maste CPPLanguageRuntime::CPPLanguageRuntime (Process *process) : 160ac7ddfbfSEd Maste LanguageRuntime (process) 161ac7ddfbfSEd Maste { 162ac7ddfbfSEd Maste 163ac7ddfbfSEd Maste } 164ac7ddfbfSEd Maste 165ac7ddfbfSEd Maste bool 166ac7ddfbfSEd Maste CPPLanguageRuntime::GetObjectDescription (Stream &str, ValueObject &object) 167ac7ddfbfSEd Maste { 168ac7ddfbfSEd Maste // C++ has no generic way to do this. 169ac7ddfbfSEd Maste return false; 170ac7ddfbfSEd Maste } 171ac7ddfbfSEd Maste 172ac7ddfbfSEd Maste bool 173ac7ddfbfSEd Maste CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope) 174ac7ddfbfSEd Maste { 175ac7ddfbfSEd Maste // C++ has no generic way to do this. 176ac7ddfbfSEd Maste return false; 177ac7ddfbfSEd Maste } 178ac7ddfbfSEd Maste 179ac7ddfbfSEd Maste bool 180ac7ddfbfSEd Maste CPPLanguageRuntime::IsCPPMangledName (const char *name) 181ac7ddfbfSEd Maste { 182ac7ddfbfSEd Maste // FIXME, we should really run through all the known C++ Language plugins and ask each one if 183ac7ddfbfSEd Maste // this is a C++ mangled name, but we can put that off till there is actually more than one 184ac7ddfbfSEd Maste // we care about. 185ac7ddfbfSEd Maste 186ac7ddfbfSEd Maste if (name && name[0] == '_' && name[1] == 'Z') 187ac7ddfbfSEd Maste return true; 188ac7ddfbfSEd Maste else 189ac7ddfbfSEd Maste return false; 190ac7ddfbfSEd Maste } 191ac7ddfbfSEd Maste 192ac7ddfbfSEd Maste bool 193ac7ddfbfSEd Maste CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end) 194ac7ddfbfSEd Maste { 195ac7ddfbfSEd Maste if (base_name_end == NULL) 196ac7ddfbfSEd Maste base_name_end = name + strlen (name); 197ac7ddfbfSEd Maste 198ac7ddfbfSEd Maste const char *last_colon = strrchr (name, ':'); 199ac7ddfbfSEd Maste 200ac7ddfbfSEd Maste if (last_colon == NULL) 201ac7ddfbfSEd Maste { 202ac7ddfbfSEd Maste base_name_start = name; 203ac7ddfbfSEd Maste return true; 204ac7ddfbfSEd Maste } 205ac7ddfbfSEd Maste 206ac7ddfbfSEd Maste // Can't have a C++ name that begins with a single ':', nor contains an internal single ':' 207ac7ddfbfSEd Maste if (last_colon == name) 208ac7ddfbfSEd Maste return false; 209ac7ddfbfSEd Maste else if (last_colon[-1] != ':') 210ac7ddfbfSEd Maste return false; 211ac7ddfbfSEd Maste else 212ac7ddfbfSEd Maste { 213ac7ddfbfSEd Maste // FIXME: should check if there is 214ac7ddfbfSEd Maste base_name_start = last_colon + 1; 215ac7ddfbfSEd Maste return true; 216ac7ddfbfSEd Maste } 217ac7ddfbfSEd Maste } 218ac7ddfbfSEd Maste 219ac7ddfbfSEd Maste uint32_t 220ac7ddfbfSEd Maste CPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents) 221ac7ddfbfSEd Maste { 222ac7ddfbfSEd Maste uint32_t count = GetEquivalentsMap().FindExactMatches(type_name, equivalents); 223ac7ddfbfSEd Maste 224ac7ddfbfSEd Maste bool might_have_partials= 225ac7ddfbfSEd Maste ( count == 0 ) // if we have a full name match just use it 226ac7ddfbfSEd Maste && (strchr(type_name.AsCString(), '<') != NULL // we should only have partial matches when templates are involved, check that we have 227ac7ddfbfSEd Maste && strchr(type_name.AsCString(), '>') != NULL); // angle brackets in the type_name before trying to scan for partial matches 228ac7ddfbfSEd Maste 229ac7ddfbfSEd Maste if ( might_have_partials ) 230ac7ddfbfSEd Maste count = GetEquivalentsMap().FindPartialMatches(type_name, equivalents); 231ac7ddfbfSEd Maste 232ac7ddfbfSEd Maste return count; 233ac7ddfbfSEd Maste } 234ac7ddfbfSEd Maste 235ac7ddfbfSEd Maste void 236ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::Clear() 237ac7ddfbfSEd Maste { 238ac7ddfbfSEd Maste m_full.Clear(); 239ac7ddfbfSEd Maste m_basename = llvm::StringRef(); 240ac7ddfbfSEd Maste m_context = llvm::StringRef(); 241ac7ddfbfSEd Maste m_arguments = llvm::StringRef(); 242ac7ddfbfSEd Maste m_qualifiers = llvm::StringRef(); 243ac7ddfbfSEd Maste m_type = eTypeInvalid; 244ac7ddfbfSEd Maste m_parsed = false; 245ac7ddfbfSEd Maste m_parse_error = false; 246ac7ddfbfSEd Maste } 247ac7ddfbfSEd Maste 248ac7ddfbfSEd Maste bool 249ac7ddfbfSEd Maste ReverseFindMatchingChars (const llvm::StringRef &s, 250ac7ddfbfSEd Maste const llvm::StringRef &left_right_chars, 251ac7ddfbfSEd Maste size_t &left_pos, 252ac7ddfbfSEd Maste size_t &right_pos, 253ac7ddfbfSEd Maste size_t pos = llvm::StringRef::npos) 254ac7ddfbfSEd Maste { 255ac7ddfbfSEd Maste assert (left_right_chars.size() == 2); 256ac7ddfbfSEd Maste left_pos = llvm::StringRef::npos; 257ac7ddfbfSEd Maste const char left_char = left_right_chars[0]; 258ac7ddfbfSEd Maste const char right_char = left_right_chars[1]; 259ac7ddfbfSEd Maste pos = s.find_last_of(left_right_chars, pos); 260ac7ddfbfSEd Maste if (pos == llvm::StringRef::npos || s[pos] == left_char) 261ac7ddfbfSEd Maste return false; 262ac7ddfbfSEd Maste right_pos = pos; 263ac7ddfbfSEd Maste uint32_t depth = 1; 264ac7ddfbfSEd Maste while (pos > 0 && depth > 0) 265ac7ddfbfSEd Maste { 266ac7ddfbfSEd Maste pos = s.find_last_of(left_right_chars, pos); 267ac7ddfbfSEd Maste if (pos == llvm::StringRef::npos) 268ac7ddfbfSEd Maste return false; 269ac7ddfbfSEd Maste if (s[pos] == left_char) 270ac7ddfbfSEd Maste { 271ac7ddfbfSEd Maste if (--depth == 0) 272ac7ddfbfSEd Maste { 273ac7ddfbfSEd Maste left_pos = pos; 274ac7ddfbfSEd Maste return left_pos < right_pos; 275ac7ddfbfSEd Maste } 276ac7ddfbfSEd Maste } 277ac7ddfbfSEd Maste else if (s[pos] == right_char) 278ac7ddfbfSEd Maste { 279ac7ddfbfSEd Maste ++depth; 280ac7ddfbfSEd Maste } 281ac7ddfbfSEd Maste } 282ac7ddfbfSEd Maste return false; 283ac7ddfbfSEd Maste } 284ac7ddfbfSEd Maste 285ac7ddfbfSEd Maste void 286ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::Parse() 287ac7ddfbfSEd Maste { 288ac7ddfbfSEd Maste if (!m_parsed && m_full) 289ac7ddfbfSEd Maste { 290ac7ddfbfSEd Maste // ConstString mangled; 291ac7ddfbfSEd Maste // m_full.GetMangledCounterpart(mangled); 292ac7ddfbfSEd Maste // printf ("\n parsing = '%s'\n", m_full.GetCString()); 293ac7ddfbfSEd Maste // if (mangled) 294ac7ddfbfSEd Maste // printf (" mangled = '%s'\n", mangled.GetCString()); 295ac7ddfbfSEd Maste m_parse_error = false; 296ac7ddfbfSEd Maste m_parsed = true; 297ac7ddfbfSEd Maste llvm::StringRef full (m_full.GetCString()); 298ac7ddfbfSEd Maste 299ac7ddfbfSEd Maste size_t arg_start, arg_end; 300ac7ddfbfSEd Maste llvm::StringRef parens("()", 2); 301ac7ddfbfSEd Maste if (ReverseFindMatchingChars (full, parens, arg_start, arg_end)) 302ac7ddfbfSEd Maste { 303ac7ddfbfSEd Maste m_arguments = full.substr(arg_start, arg_end - arg_start + 1); 304ac7ddfbfSEd Maste if (arg_end + 1 < full.size()) 305ac7ddfbfSEd Maste m_qualifiers = full.substr(arg_end + 1); 306ac7ddfbfSEd Maste if (arg_start > 0) 307ac7ddfbfSEd Maste { 308ac7ddfbfSEd Maste size_t basename_end = arg_start; 309ac7ddfbfSEd Maste size_t context_end = llvm::StringRef::npos; 310ac7ddfbfSEd Maste if (basename_end > 0 && full[basename_end-1] == '>') 311ac7ddfbfSEd Maste { 312ac7ddfbfSEd Maste // TODO: handle template junk... 313ac7ddfbfSEd Maste // Templated function 314ac7ddfbfSEd Maste size_t template_start, template_end; 315ac7ddfbfSEd Maste llvm::StringRef lt_gt("<>", 2); 316ac7ddfbfSEd Maste if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end)) 317ac7ddfbfSEd Maste context_end = full.rfind(':', template_start); 318ac7ddfbfSEd Maste } 319ac7ddfbfSEd Maste if (context_end == llvm::StringRef::npos) 320ac7ddfbfSEd Maste context_end = full.rfind(':', basename_end); 321ac7ddfbfSEd Maste 322ac7ddfbfSEd Maste if (context_end == llvm::StringRef::npos) 323ac7ddfbfSEd Maste m_basename = full.substr(0, basename_end); 324ac7ddfbfSEd Maste else 325ac7ddfbfSEd Maste { 326ac7ddfbfSEd Maste m_context = full.substr(0, context_end - 1); 327ac7ddfbfSEd Maste const size_t basename_begin = context_end + 1; 328ac7ddfbfSEd Maste m_basename = full.substr(basename_begin, basename_end - basename_begin); 329ac7ddfbfSEd Maste } 330ac7ddfbfSEd Maste m_type = eTypeUnknownMethod; 331ac7ddfbfSEd Maste } 332ac7ddfbfSEd Maste else 333ac7ddfbfSEd Maste { 334ac7ddfbfSEd Maste m_parse_error = true; 335ac7ddfbfSEd Maste return; 336ac7ddfbfSEd Maste } 337ac7ddfbfSEd Maste 338ac7ddfbfSEd Maste // if (!m_context.empty()) 339ac7ddfbfSEd Maste // printf (" context = '%s'\n", m_context.str().c_str()); 340ac7ddfbfSEd Maste // if (m_basename) 341ac7ddfbfSEd Maste // printf (" basename = '%s'\n", m_basename.GetCString()); 342ac7ddfbfSEd Maste // if (!m_arguments.empty()) 343ac7ddfbfSEd Maste // printf (" arguments = '%s'\n", m_arguments.str().c_str()); 344ac7ddfbfSEd Maste // if (!m_qualifiers.empty()) 345ac7ddfbfSEd Maste // printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str()); 346ac7ddfbfSEd Maste } 347ac7ddfbfSEd Maste else 348ac7ddfbfSEd Maste { 349ac7ddfbfSEd Maste m_parse_error = true; 350ac7ddfbfSEd Maste // printf ("error: didn't find matching parens for arguments\n"); 351ac7ddfbfSEd Maste } 352ac7ddfbfSEd Maste } 353ac7ddfbfSEd Maste } 354ac7ddfbfSEd Maste 355ac7ddfbfSEd Maste llvm::StringRef 356ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::GetBasename () 357ac7ddfbfSEd Maste { 358ac7ddfbfSEd Maste if (!m_parsed) 359ac7ddfbfSEd Maste Parse(); 360ac7ddfbfSEd Maste return m_basename; 361ac7ddfbfSEd Maste } 362ac7ddfbfSEd Maste 363ac7ddfbfSEd Maste llvm::StringRef 364ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::GetContext () 365ac7ddfbfSEd Maste { 366ac7ddfbfSEd Maste if (!m_parsed) 367ac7ddfbfSEd Maste Parse(); 368ac7ddfbfSEd Maste return m_context; 369ac7ddfbfSEd Maste } 370ac7ddfbfSEd Maste 371ac7ddfbfSEd Maste llvm::StringRef 372ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::GetArguments () 373ac7ddfbfSEd Maste { 374ac7ddfbfSEd Maste if (!m_parsed) 375ac7ddfbfSEd Maste Parse(); 376ac7ddfbfSEd Maste return m_arguments; 377ac7ddfbfSEd Maste } 378ac7ddfbfSEd Maste 379ac7ddfbfSEd Maste llvm::StringRef 380ac7ddfbfSEd Maste CPPLanguageRuntime::MethodName::GetQualifiers () 381ac7ddfbfSEd Maste { 382ac7ddfbfSEd Maste if (!m_parsed) 383ac7ddfbfSEd Maste Parse(); 384ac7ddfbfSEd Maste return m_qualifiers; 385ac7ddfbfSEd Maste } 386ac7ddfbfSEd Maste 387