blob: c3657952c16729090897fb5f83ca1391dff1a317 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Mangled.cpp ---------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include <cxxabi.h>
11
Greg Claytone41e5892010-09-03 23:26:12 +000012#include "llvm/ADT/DenseMap.h"
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Core/ConstString.h"
15#include "lldb/Core/Mangled.h"
16#include "lldb/Core/Stream.h"
17#include "lldb/Core/Timer.h"
Eli Friedman88966972010-06-09 08:50:27 +000018#include <ctype.h>
19#include <string.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020
21using namespace lldb_private;
22
23#pragma mark Mangled
24//----------------------------------------------------------------------
25// Default constructor
26//----------------------------------------------------------------------
27Mangled::Mangled () :
28 m_mangled(),
29 m_demangled()
30{
31}
32
33//----------------------------------------------------------------------
34// Constructor with an optional string and a boolean indicating if it is
35// the mangled version.
36//----------------------------------------------------------------------
37Mangled::Mangled (const char *s, bool mangled) :
38 m_mangled(),
39 m_demangled()
40{
41 if (s && s[0])
42 {
43 SetValue(s, mangled);
44 }
45}
46
47//----------------------------------------------------------------------
48// Destructor
49//----------------------------------------------------------------------
50Mangled::~Mangled ()
51{
52}
53
54//----------------------------------------------------------------------
55// Convert to pointer operator. This allows code to check any Mangled
56// objects to see if they contain anything valid using code such as:
57//
58// Mangled mangled(...);
59// if (mangled)
60// { ...
61//----------------------------------------------------------------------
62Mangled::operator void* () const
63{
64 return (m_mangled) ? const_cast<Mangled*>(this) : NULL;
65}
66
67//----------------------------------------------------------------------
68// Logical NOT operator. This allows code to check any Mangled
69// objects to see if they are invalid using code such as:
70//
71// Mangled mangled(...);
72// if (!file_spec)
73// { ...
74//----------------------------------------------------------------------
75bool
76Mangled::operator! () const
77{
78 return !m_mangled;
79}
80
81//----------------------------------------------------------------------
82// Clear the mangled and demangled values.
83//----------------------------------------------------------------------
84void
85Mangled::Clear ()
86{
87 m_mangled.Clear();
88 m_demangled.Clear();
89}
90
91
92//----------------------------------------------------------------------
93// Compare the the string values.
94//----------------------------------------------------------------------
95int
96Mangled::Compare (const Mangled& a, const Mangled& b)
97{
98 return ConstString::Compare(a.GetName(), a.GetName());
99}
100
101
102
103//----------------------------------------------------------------------
104// Set the string value in this objects. If "mangled" is true, then
105// the mangled named is set with the new value in "s", else the
106// demangled name is set.
107//----------------------------------------------------------------------
108void
109Mangled::SetValue (const char *s, bool mangled)
110{
111 m_mangled.Clear();
112 m_demangled.Clear();
113
114 if (s)
115 {
116 if (mangled)
117 m_mangled.SetCString (s);
118 else
119 m_demangled.SetCString(s);
120 }
121}
122
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123//----------------------------------------------------------------------
124// Generate the demangled name on demand using this accessor. Code in
125// this class will need to use this accessor if it wishes to decode
126// the demangled name. The result is cached and will be kept until a
127// new string value is supplied to this object, or until the end of the
128// object's lifetime.
129//----------------------------------------------------------------------
130const ConstString&
131Mangled::GetDemangledName () const
132{
133 // Check to make sure we have a valid mangled name and that we
134 // haven't already decoded our mangled name.
135 if (m_mangled && !m_demangled)
136 {
137 // We need to generate and cache the demangled name.
138 Timer scoped_timer (__PRETTY_FUNCTION__,
139 "Mangled::GetDemangledName (m_mangled = %s)",
140 m_mangled.GetCString());
141
142 // We already know mangled is valid from the above check,
143 // lets just make sure it isn't empty...
144 const char * mangled = m_mangled.AsCString();
145 if (mangled[0])
146 {
Greg Claytone41e5892010-09-03 23:26:12 +0000147 // Since demangling can be a costly, and since all names that go
148 // into a ConstString (like our m_mangled and m_demangled members)
149 // end up being unique "const char *" values, we can use a DenseMap
150 // to speed up our lookup. We do this because often our symbol table
151 // and our debug information both have the mangled names which they
152 // would each need to demangle. Also, with GCC we end up with the one
153 // definition rule where a lot of STL code produces symbols that are
154 // in multiple compile units and the mangled names end up being in
155 // the same binary multiple times. The performance win isn't huge,
156 // but we showed a 20% improvement on darwin.
157 typedef llvm::DenseMap<const char *, const char *> MangledToDemangledMap;
158 static MangledToDemangledMap g_mangled_to_demangled;
Benjamin Kramer53a61dc2010-06-22 15:28:29 +0000159
Greg Claytone41e5892010-09-03 23:26:12 +0000160 // Check our mangled string pointer to demangled string pointer map first
161 MangledToDemangledMap::const_iterator pos = g_mangled_to_demangled.find (mangled);
162 if (pos != g_mangled_to_demangled.end())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000163 {
Greg Claytone41e5892010-09-03 23:26:12 +0000164 // We have already demangled this string, we can just use our saved result!
165 m_demangled.SetCString(pos->second);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 }
167 else
168 {
Greg Claytone41e5892010-09-03 23:26:12 +0000169 // We didn't already mangle this name, demangle it and if all goes well
170 // add it to our map.
171 char *demangled_name = abi::__cxa_demangle (mangled, NULL, NULL, NULL);
172
173 if (demangled_name)
174 {
175 m_demangled.SetCString (demangled_name);
176 // Now that the name has been uniqued, add the uniqued C string
177 // pointer from m_mangled as the key to the uniqued C string
178 // pointer in m_demangled.
179 g_mangled_to_demangled.insert (std::make_pair (mangled, m_demangled.GetCString()));
180 free (demangled_name);
181 }
182 else
183 {
184 // Set the demangled string to the empty string to indicate we
185 // tried to parse it once and failed.
186 m_demangled.SetCString("");
187 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 }
189 }
190 }
191
192 return m_demangled;
193}
194
195//----------------------------------------------------------------------
196// Mangled name get accessor
197//----------------------------------------------------------------------
198ConstString&
199Mangled::GetMangledName ()
200{
201 return m_mangled;
202}
203
204//----------------------------------------------------------------------
205// Mangled name const get accessor
206//----------------------------------------------------------------------
207const ConstString&
208Mangled::GetMangledName () const
209{
210 return m_mangled;
211}
212
213//----------------------------------------------------------------------
214// Get the demangled name if there is one, else return the mangled name.
215//----------------------------------------------------------------------
216const ConstString&
217Mangled::GetName () const
218{
219 const ConstString& name = GetDemangledName();
220 if (name && !name.IsEmpty())
221 return name;
222 return m_mangled;
223}
224
225//----------------------------------------------------------------------
226// Generate the tokens from the demangled name.
227//
228// Returns the number of tokens that were parsed.
229//----------------------------------------------------------------------
230size_t
231Mangled::GetTokens (Mangled::TokenList &tokens) const
232{
233 tokens.Clear();
234 const ConstString& demangled = GetDemangledName();
235 if (demangled && !demangled.IsEmpty())
236 tokens.Parse(demangled.AsCString());
237
238 return tokens.Size();
239}
240
241//----------------------------------------------------------------------
242// Dump a Mangled object to stream "s". We don't force our
243// demangled name to be computed currently (we don't use the accessor).
244//----------------------------------------------------------------------
245void
246Mangled::Dump (Stream *s) const
247{
248 if (m_mangled)
249 {
250 *s << ", mangled = " << m_mangled;
251 }
252 if (m_demangled)
253 {
254 const char * demangled = m_demangled.AsCString();
255 s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>");
256 }
257}
258
259//----------------------------------------------------------------------
260// Dumps a debug version of this string with extra object and state
261// information to stream "s".
262//----------------------------------------------------------------------
263void
264Mangled::DumpDebug (Stream *s) const
265{
266 s->Printf("%*p: Mangled mangled = ", (int)sizeof(void*) * 2, this);
267 m_mangled.DumpDebug(s);
268 s->Printf(", demangled = ");
269 m_demangled.DumpDebug(s);
270}
271
272//----------------------------------------------------------------------
273// Return the size in byte that this object takes in memory. The size
274// includes the size of the objects it owns, and not the strings that
275// it references because they are shared strings.
276//----------------------------------------------------------------------
277size_t
278Mangled::MemorySize () const
279{
280 return m_mangled.MemorySize() + m_demangled.MemorySize();
281}
282
283//----------------------------------------------------------------------
284// Dump OBJ to the supplied stream S.
285//----------------------------------------------------------------------
286Stream&
287operator << (Stream& s, const Mangled& obj)
288{
289 if (obj.GetMangledName())
290 s << "mangled = '" << obj.GetMangledName() << "'";
291
292 const ConstString& demangled = obj.GetDemangledName();
293 if (demangled)
294 s << ", demangled = '" << demangled << '\'';
295 else
296 s << ", demangled = <error>";
297 return s;
298}
299
300
301
302
303#pragma mark Mangled::Token
304
305//--------------------------------------------------------------
306// Default constructor
307//--------------------------------------------------------------
308Mangled::Token::Token () :
309 type(eInvalid),
310 value()
311{
312}
313
314//--------------------------------------------------------------
315// Equal to operator
316//--------------------------------------------------------------
317bool
318Mangled::Token::operator== (const Token& rhs) const
319{
320 return type == rhs.type && value == rhs.value;
321}
322
323//--------------------------------------------------------------
324// Dump the token to a stream "s"
325//--------------------------------------------------------------
326void
327Mangled::Token::Dump (Stream *s) const
328{
329 switch (type)
330 {
331 case eInvalid: s->PutCString("invalid "); break;
332 case eNameSpace: s->PutCString("namespace "); break;
333 case eMethodName: s->PutCString("method "); break;
334 case eType: s->PutCString("type "); break;
335 case eTemplate: s->PutCString("template "); break;
336 case eTemplateBeg: s->PutCString("template < "); break;
337 case eTemplateEnd: s->PutCString("template > "); break;
338 case eParamsBeg: s->PutCString("params ( "); break;
339 case eParamsEnd: s->PutCString("params ) "); break;
340 case eQualifier: s->PutCString("qualifier "); break;
341 case eError: s->PutCString("ERROR "); break;
342 default:
343 s->Printf("type = %i", type);
344 break;
345 }
346 value.DumpDebug(s);
347}
348
349//--------------------------------------------------------------
350// Returns true if this token is a wildcard
351//--------------------------------------------------------------
352bool
353Mangled::Token::IsWildcard () const
354{
355 static ConstString g_wildcard_str("*");
356 return value == g_wildcard_str;
357}
358
359
360//----------------------------------------------------------------------
361// Dump "obj" to the supplied stream "s"
362//----------------------------------------------------------------------
363Stream&
364lldb_private::operator << (Stream& s, const Mangled::Token& obj)
365{
366 obj.Dump(&s);
367 return s;
368}
369
370
371#pragma mark Mangled::TokenList
372//----------------------------------------------------------------------
373// Mangled::TokenList
374//----------------------------------------------------------------------
375
376//--------------------------------------------------------------
377// Default constructor. If demangled is non-NULL and not-empty
378// the token list will parse up the demangled string it is
379// given, else the object will initialize an empty token list.
380//--------------------------------------------------------------
381Mangled::TokenList::TokenList (const char *demangled) :
382 m_tokens()
383{
384 if (demangled && demangled[0])
385 {
386 Parse(demangled);
387 }
388}
389
390//----------------------------------------------------------------------
391// Destructor
392//----------------------------------------------------------------------
393Mangled::TokenList::~TokenList ()
394{
395}
396
397//----------------------------------------------------------------------
398// Parses "demangled" into tokens. This allows complex
399// comparisons to be done. Comparisons can include wildcards at
400// the namespace, method name, template, and template and
401// parameter type levels.
402//
403// Example queries include:
404// "std::basic_string<*>" // Find all std::basic_string variants
405// "std::basic_string<*>::erase(*)" // Find all std::basic_string::erase variants with any number of parameters
406// "*::clear()" // Find all functions with a method name of
407// // "clear" that are in any namespace that
408// // have no parameters
409// "::printf" // Find the printf function in the global namespace
410// "printf" // Ditto
411// "foo::*(int)" // Find all functions in the class or namespace "foo" that take a single integer argument
412//
413// Returns the number of tokens that were decoded, or zero when
414// we fail.
415//----------------------------------------------------------------------
416size_t
417Mangled::TokenList::Parse (const char *s)
418{
419 m_tokens.clear();
420
421 Token token;
422 token.type = eNameSpace;
423
424 TokenType max_type = eInvalid;
425 const char *p = s;
426 size_t span = 0;
427 size_t sep_size = 0;
428
429 while (*p != '\0')
430 {
431 p = p + span + sep_size;
432 while (isspace(*p))
433 ++p;
434
435 if (*p == '\0')
436 break;
437
438 span = strcspn(p, ":<>(),");
439 sep_size = 1;
440 token.type = eInvalid;
441 switch (p[span])
442 {
443 case '\0':
444 break;
445
446 case ':':
447 if (p[span+1] == ':')
448 {
449 sep_size = 2;
450 if (span > 0)
451 {
452 token.type = eNameSpace;
453 token.value.SetCStringWithLength (p, span);
454 m_tokens.push_back(token);
455 }
456 else
457 continue;
458 }
459 break;
460
461 case '(':
462 if (span > 0)
463 {
464 token.type = eMethodName;
465 token.value.SetCStringWithLength (p, span);
466 m_tokens.push_back(token);
467 }
468
469 token.type = eParamsBeg;
470 token.value.Clear();
471 m_tokens.push_back(token);
472 break;
473
474 case ',':
475 if (span > 0)
476 {
477 token.type = eType;
478 token.value.SetCStringWithLength (p, span);
479 m_tokens.push_back(token);
480 }
481 else
482 {
483 continue;
484 }
485 break;
486
487 case ')':
488 if (span > 0)
489 {
490 token.type = eType;
491 token.value.SetCStringWithLength (p, span);
492 m_tokens.push_back(token);
493 }
494
495 token.type = eParamsEnd;
496 token.value.Clear();
497 m_tokens.push_back(token);
498 break;
499
500 case '<':
501 if (span > 0)
502 {
503 token.type = eTemplate;
504 token.value.SetCStringWithLength (p, span);
505 m_tokens.push_back(token);
506 }
507
508 token.type = eTemplateBeg;
509 token.value.Clear();
510 m_tokens.push_back(token);
511 break;
512
513 case '>':
514 if (span > 0)
515 {
516 token.type = eType;
517 token.value.SetCStringWithLength (p, span);
518 m_tokens.push_back(token);
519 }
520
521 token.type = eTemplateEnd;
522 token.value.Clear();
523 m_tokens.push_back(token);
524 break;
525 }
526
527 if (max_type < token.type)
528 max_type = token.type;
529
530 if (token.type == eInvalid)
531 {
532 if (max_type >= eParamsEnd)
533 {
534 token.type = eQualifier;
535 token.value.SetCString(p);
536 m_tokens.push_back(token);
537 }
538 else if (max_type >= eParamsBeg)
539 {
540 token.type = eType;
541 token.value.SetCString(p);
542 m_tokens.push_back(token);
543 }
544 else
545 {
546 token.type = eMethodName;
547 token.value.SetCString(p);
548 m_tokens.push_back(token);
549 }
550 break;
551 }
552 }
553 return m_tokens.size();
554}
555
556
557//----------------------------------------------------------------------
558// Clear the token list.
559//----------------------------------------------------------------------
560void
561Mangled::TokenList::Clear ()
562{
563 m_tokens.clear();
564}
565
566//----------------------------------------------------------------------
567// Dump the token list to the stream "s"
568//----------------------------------------------------------------------
569void
570Mangled::TokenList::Dump (Stream *s) const
571{
572 collection::const_iterator pos;
573 collection::const_iterator beg = m_tokens.begin();
574 collection::const_iterator end = m_tokens.end();
575 for (pos = beg; pos != end; ++pos)
576 {
577 s->Indent("token[");
578 *s << (uint32_t)std::distance(beg, pos) << "] = " << *pos << "\n";
579 }
580}
581
582//----------------------------------------------------------------------
583// Find the first token in the list that has "token_type" as its
584// type
585//----------------------------------------------------------------------
586const Mangled::Token *
587Mangled::TokenList::Find (TokenType token_type) const
588{
589 collection::const_iterator pos;
590 collection::const_iterator beg = m_tokens.begin();
591 collection::const_iterator end = m_tokens.end();
592 for (pos = beg; pos != end; ++pos)
593 {
594 if (pos->type == token_type)
595 return &(*pos);
596 }
597 return NULL;
598}
599
600//----------------------------------------------------------------------
601// Return the token at index "idx", or NULL if the index is
602// out of range.
603//----------------------------------------------------------------------
604const Mangled::Token *
605Mangled::TokenList::GetTokenAtIndex (uint32_t idx) const
606{
607 if (idx < m_tokens.size())
608 return &m_tokens[idx];
609 return NULL;
610}
611
612
613//----------------------------------------------------------------------
614// Given a token list, see if it matches this object's tokens.
615// "token_list" can contain wild card values to enable powerful
616// matching. Matching the std::string::erase(*) example that was
617// tokenized above we could use a token list such as:
618//
619// token name
620// ----------- ----------------------------------------
621// eNameSpace "std"
622// eTemplate "basic_string"
623// eTemplateBeg
624// eInvalid "*"
625// eTemplateEnd
626// eMethodName "erase"
627// eParamsBeg
628// eInvalid "*"
629// eParamsEnd
630//
631// Returns true if it "token_list" matches this object's tokens,
632// false otherwise.
633//----------------------------------------------------------------------
634bool
635Mangled::TokenList::MatchesQuery (const Mangled::TokenList &match) const
636{
637 size_t match_count = 0;
638 collection::const_iterator pos;
639 collection::const_iterator pos_end = m_tokens.end();
640
641 collection::const_iterator match_pos;
642 collection::const_iterator match_pos_end = match.m_tokens.end();
643 collection::const_iterator match_wildcard_pos = match_pos_end;
644 collection::const_iterator match_next_pos = match_pos_end;
645
646 size_t template_scope_depth = 0;
647
648 for (pos = m_tokens.begin(), match_pos = match.m_tokens.begin();
649 pos != pos_end && match_pos != match_pos_end;
650 ++match_pos)
651 {
652 match_next_pos = match_pos + 1;
653 // Is this a wildcard?
654 if (match_pos->IsWildcard())
655 {
656 if (match_wildcard_pos != match_pos_end)
657 return false; // Can't have two wildcards in effect at once.
658
659 match_wildcard_pos = match_pos;
660 // Are we at the end of the MATCH token list?
661 if (match_next_pos == match_pos_end)
662 {
663 // There is nothing more to match, return if we have any matches so far...
664 return match_count > 0;
665 }
666 }
667
668 if (match_pos->type == eInvalid || match_pos->type == eError)
669 {
670 return false;
671 }
672 else
673 {
674 if (match_pos->type == eTemplateBeg)
675 {
676 ++template_scope_depth;
677 }
678 else if (match_pos->type == eTemplateEnd)
679 {
680 assert(template_scope_depth > 0);
681 --template_scope_depth;
682 }
683
684 // Do we have a wildcard going right now?
685 if (match_wildcard_pos == match_pos_end)
686 {
687 // No wildcard matching right now, just check and see if things match
688 if (*pos == *match_pos)
689 ++match_count;
690 else
691 return false;
692 }
693 else
694 {
695 // We have a wildcard match going
696
697 // For template types we need to make sure to match the template depths...
698 const size_t start_wildcard_template_scope_depth = template_scope_depth;
699 size_t curr_wildcard_template_scope_depth = template_scope_depth;
700 while (pos != pos_end)
701 {
702 if (match_wildcard_pos->type == eNameSpace && pos->type == eParamsBeg)
703 return false;
704
705 if (start_wildcard_template_scope_depth == curr_wildcard_template_scope_depth)
706 {
707 if (*pos == *match_next_pos)
708 {
709 ++match_count;
710 match_pos = match_next_pos;
711 match_wildcard_pos = match_pos_end;
712 break;
713 }
714 }
715 if (pos->type == eTemplateBeg)
716 ++curr_wildcard_template_scope_depth;
717 else if (pos->type == eTemplateEnd)
718 --curr_wildcard_template_scope_depth;
719
720
721 ++pos;
722 }
723 }
724 }
725
726 if (pos != pos_end)
727 ++pos;
728 }
729 if (match_pos != match_pos_end)
730 return false;
731
732 return match_count > 0;
733}
734
735
736//----------------------------------------------------------------------
737// Return the number of tokens in the token collection
738//----------------------------------------------------------------------
739size_t
740Mangled::TokenList::Size () const
741{
742 return m_tokens.size();
743}
744
745
746//----------------------------------------------------------------------
747// Stream out the tokens
748//----------------------------------------------------------------------
749Stream&
750lldb_private::operator << (Stream& s, const Mangled::TokenList& obj)
751{
752 obj.Dump(&s);
753 return s;
754}