1 //===-- Type.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 // Other libraries and framework includes
11 
12 #include "lldb/Core/DataExtractor.h"
13 #include "lldb/Core/DataBufferHeap.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/Scalar.h"
16 #include "lldb/Core/StreamString.h"
17 
18 #include "lldb/Symbol/ClangASTType.h"
19 #include "lldb/Symbol/ClangASTContext.h"
20 #include "lldb/Symbol/ObjectFile.h"
21 #include "lldb/Symbol/SymbolContextScope.h"
22 #include "lldb/Symbol/SymbolFile.h"
23 #include "lldb/Symbol/Type.h"
24 #include "lldb/Symbol/TypeList.h"
25 
26 #include "lldb/Target/ExecutionContext.h"
27 #include "lldb/Target/Process.h"
28 
29 using namespace lldb;
30 
31 lldb_private::Type::Type
32 (
33     lldb::user_id_t uid,
34     SymbolFile* symbol_file,
35     const ConstString &name,
36     uint32_t byte_size,
37     SymbolContextScope *context,
38     uintptr_t encoding_data,
39     EncodingDataType encoding_data_type,
40     const Declaration& decl,
41     clang_type_t clang_type,
42     bool is_forward_decl
43 ) :
44     UserID (uid),
45     m_name (name),
46     m_symbol_file (symbol_file),
47     m_context (context),
48     m_encoding_type (NULL),
49     m_encoding_uid_type (encoding_data_type),
50     m_encoding_uid (encoding_data),
51     m_byte_size (byte_size),
52     m_decl (decl),
53     m_clang_type (clang_type),
54     m_is_forward_decl (is_forward_decl),
55     m_encoding_type_forward_decl_resolved (false),
56     m_encoding_type_decl_resolved (false)
57 {
58 }
59 
60 lldb_private::Type::Type () :
61     UserID (0),
62     m_name ("<INVALID TYPE>"),
63     m_symbol_file (NULL),
64     m_context (NULL),
65     m_encoding_type (NULL),
66     m_encoding_uid_type (eEncodingInvalid),
67     m_encoding_uid (0),
68     m_byte_size (0),
69     m_is_forward_decl (false),
70     m_decl (),
71     m_clang_type (NULL)
72 {
73 }
74 
75 
76 const lldb_private::Type&
77 lldb_private::Type::operator= (const Type& rhs)
78 {
79     if (this != &rhs)
80     {
81         UserID::operator= (rhs);
82         m_name = rhs.m_name;
83         m_symbol_file = rhs.m_symbol_file;
84         m_context = rhs.m_context;
85         m_encoding_type = rhs.m_encoding_type;
86         m_encoding_uid_type = rhs.m_encoding_uid_type;
87         m_encoding_uid = rhs.m_encoding_uid;
88         m_byte_size = rhs.m_byte_size;
89         m_is_forward_decl = rhs.m_is_forward_decl;
90         m_decl = rhs.m_decl;
91         m_clang_type = rhs.m_clang_type;
92     }
93     return *this;
94 }
95 
96 
97 void
98 lldb_private::Type::GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name)
99 {
100     *s << "id = " << (const UserID&)*this;
101 
102     // Call the name accessor to make sure we resolve the type name
103     if (show_name && GetName())
104         *s << ", name = \"" << m_name << '"';
105 
106     // Call the get byte size accesor so we resolve our byte size
107     if (GetByteSize())
108         s->Printf(", byte-size = %zu", m_byte_size);
109     bool show_fullpaths = (level == lldb::eDescriptionLevelVerbose);
110     m_decl.Dump(s, show_fullpaths);
111 
112     if (m_clang_type)
113     {
114         *s << ", clang_type = \"";
115         ClangASTType::DumpTypeDescription (GetClangAST(), m_clang_type, s);
116         *s << '"';
117     }
118     else if (m_encoding_uid != LLDB_INVALID_UID)
119     {
120         s->Printf(", type_uid = 0x%8.8x", m_encoding_uid);
121         switch (m_encoding_uid_type)
122         {
123         case eEncodingIsUID: s->PutCString(" (unresolved type)"); break;
124         case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break;
125         case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break;
126         case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break;
127         case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break;
128         case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break;
129         case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break;
130         case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break;
131         case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break;
132         }
133     }
134 }
135 
136 
137 void
138 lldb_private::Type::Dump (Stream *s, bool show_context)
139 {
140     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
141     s->Indent();
142     *s << "Type" << (const UserID&)*this << ' ';
143     if (m_name)
144         *s << ", name = \"" << m_name << "\"";
145 
146     if (m_byte_size != 0)
147         s->Printf(", size = %zu", m_byte_size);
148 
149     if (show_context && m_context != NULL)
150     {
151         s->PutCString(", context = ( ");
152         m_context->DumpSymbolContext(s);
153         s->PutCString(" )");
154     }
155 
156     bool show_fullpaths = false;
157     m_decl.Dump (s,show_fullpaths);
158 
159     if (m_clang_type)
160     {
161         *s << ", clang_type = " << m_clang_type << ' ';
162 
163         ClangASTType::DumpTypeDescription (GetClangAST(), m_clang_type, s);
164     }
165     else if (m_encoding_uid != LLDB_INVALID_UID)
166     {
167         *s << ", type_data = " << (uint64_t)m_encoding_uid;
168         switch (m_encoding_uid_type)
169         {
170         case eEncodingIsUID: s->PutCString(" (unresolved type)"); break;
171         case eEncodingIsConstUID: s->PutCString(" (unresolved const type)"); break;
172         case eEncodingIsRestrictUID: s->PutCString(" (unresolved restrict type)"); break;
173         case eEncodingIsVolatileUID: s->PutCString(" (unresolved volatile type)"); break;
174         case eEncodingIsTypedefUID: s->PutCString(" (unresolved typedef)"); break;
175         case eEncodingIsPointerUID: s->PutCString(" (unresolved pointer)"); break;
176         case eEncodingIsLValueReferenceUID: s->PutCString(" (unresolved L value reference)"); break;
177         case eEncodingIsRValueReferenceUID: s->PutCString(" (unresolved R value reference)"); break;
178         case eEncodingIsSyntheticUID: s->PutCString(" (synthetic type)"); break;
179         }
180     }
181 
182 //
183 //  if (m_access)
184 //      s->Printf(", access = %u", m_access);
185     s->EOL();
186 }
187 
188 const lldb_private::ConstString &
189 lldb_private::Type::GetName()
190 {
191     if (!(m_name))
192     {
193         if (ResolveClangType(true))
194         {
195             std::string type_name = ClangASTContext::GetTypeName (m_clang_type);
196             if (!type_name.empty())
197                 m_name.SetCString (type_name.c_str());
198         }
199     }
200     return m_name;
201 }
202 
203 void
204 lldb_private::Type::DumpTypeName(Stream *s)
205 {
206     GetName().Dump(s, "<invalid-type-name>");
207 }
208 
209 
210 void
211 lldb_private::Type::DumpValue
212 (
213     lldb_private::ExecutionContext *exe_ctx,
214     lldb_private::Stream *s,
215     const lldb_private::DataExtractor &data,
216     uint32_t data_byte_offset,
217     bool show_types,
218     bool show_summary,
219     bool verbose,
220     lldb::Format format
221 )
222 {
223     if (ResolveClangType(true))
224     {
225         if (show_types)
226         {
227             s->PutChar('(');
228             if (verbose)
229                 s->Printf("Type{0x%8.8x} ", GetID());
230             DumpTypeName (s);
231             s->PutCString(") ");
232         }
233 
234         lldb_private::ClangASTType::DumpValue (GetClangAST (),
235                                                m_clang_type,
236                                                exe_ctx,
237                                                s,
238                                                format == lldb::eFormatDefault ? GetFormat() : format,
239                                                data,
240                                                data_byte_offset,
241                                                GetByteSize(),
242                                                0, // Bitfield bit size
243                                                0, // Bitfield bit offset
244                                                show_types,
245                                                show_summary,
246                                                verbose,
247                                                0);
248     }
249 }
250 
251 lldb_private::Type *
252 lldb_private::Type::GetEncodingType ()
253 {
254     if (m_encoding_type == NULL)
255     {
256         if (m_encoding_uid != LLDB_INVALID_UID)
257             m_encoding_type = m_symbol_file->ResolveTypeUID(m_encoding_uid);
258     }
259     return m_encoding_type;
260 }
261 
262 
263 
264 uint64_t
265 lldb_private::Type::GetByteSize()
266 {
267     if (m_byte_size == 0)
268     {
269         switch (m_encoding_uid_type)
270         {
271         case eEncodingIsUID:
272         case eEncodingIsConstUID:
273         case eEncodingIsRestrictUID:
274         case eEncodingIsVolatileUID:
275         case eEncodingIsTypedefUID:
276             {
277                 Type *encoding_type = GetEncodingType ();
278                 if (encoding_type)
279                     m_byte_size = encoding_type->GetByteSize();
280                 if (m_byte_size == 0)
281                 {
282                     uint64_t bit_width = ClangASTType::GetClangTypeBitWidth (GetClangAST(), GetClangType());
283                     m_byte_size = (bit_width + 7 ) / 8;
284                 }
285             }
286             break;
287 
288         // If we are a pointer or reference, then this is just a pointer size;
289         case eEncodingIsPointerUID:
290         case eEncodingIsLValueReferenceUID:
291         case eEncodingIsRValueReferenceUID:
292             m_byte_size = GetTypeList()->GetClangASTContext().GetPointerBitSize() / 8;
293             break;
294         }
295     }
296     return m_byte_size;
297 }
298 
299 
300 uint32_t
301 lldb_private::Type::GetNumChildren (bool omit_empty_base_classes)
302 {
303     if (!ResolveClangType())
304         return 0;
305     return ClangASTContext::GetNumChildren (m_clang_type, omit_empty_base_classes);
306 
307 }
308 
309 bool
310 lldb_private::Type::IsAggregateType ()
311 {
312     if (ResolveClangType())
313         return ClangASTContext::IsAggregateType (m_clang_type);
314     return false;
315 }
316 
317 lldb::Format
318 lldb_private::Type::GetFormat ()
319 {
320     // Make sure we resolve our type if it already hasn't been.
321     if (!ResolveClangType())
322         return lldb::eFormatInvalid;
323     return lldb_private::ClangASTType::GetFormat (m_clang_type);
324 }
325 
326 
327 
328 lldb::Encoding
329 lldb_private::Type::GetEncoding (uint32_t &count)
330 {
331     // Make sure we resolve our type if it already hasn't been.
332     if (!ResolveClangType())
333         return lldb::eEncodingInvalid;
334 
335     return lldb_private::ClangASTType::GetEncoding (m_clang_type, count);
336 }
337 
338 
339 
340 bool
341 lldb_private::Type::DumpValueInMemory
342 (
343     lldb_private::ExecutionContext *exe_ctx,
344     lldb_private::Stream *s,
345     lldb::addr_t address,
346     lldb::AddressType address_type,
347     bool show_types,
348     bool show_summary,
349     bool verbose
350 )
351 {
352     if (address != LLDB_INVALID_ADDRESS)
353     {
354         lldb_private::DataExtractor data;
355         data.SetByteOrder (exe_ctx->process->GetByteOrder());
356         if (ReadFromMemory (exe_ctx, address, address_type, data))
357         {
358             DumpValue(exe_ctx, s, data, 0, show_types, show_summary, verbose);
359             return true;
360         }
361     }
362     return false;
363 }
364 
365 
366 bool
367 lldb_private::Type::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx, lldb::addr_t addr, lldb::AddressType address_type, lldb_private::DataExtractor &data)
368 {
369     if (address_type == lldb::eAddressTypeFile)
370     {
371         // Can't convert a file address to anything valid without more
372         // context (which Module it came from)
373         return false;
374     }
375 
376     const uint32_t byte_size = GetByteSize();
377     if (data.GetByteSize() < byte_size)
378     {
379         lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
380         data.SetData(data_sp);
381     }
382 
383     uint8_t* dst = (uint8_t*)data.PeekData(0, byte_size);
384     if (dst != NULL)
385     {
386         if (address_type == lldb::eAddressTypeHost)
387         {
388             // The address is an address in this process, so just copy it
389             memcpy (dst, (uint8_t*)NULL + addr, byte_size);
390             return true;
391         }
392         else
393         {
394             if (exe_ctx && exe_ctx->process)
395             {
396                 Error error;
397                 return exe_ctx->process->ReadMemory(addr, dst, byte_size, error) == byte_size;
398             }
399         }
400     }
401     return false;
402 }
403 
404 
405 bool
406 lldb_private::Type::WriteToMemory (lldb_private::ExecutionContext *exe_ctx, lldb::addr_t addr, lldb::AddressType address_type, lldb_private::DataExtractor &data)
407 {
408     return false;
409 }
410 
411 
412 lldb_private::TypeList*
413 lldb_private::Type::GetTypeList()
414 {
415     return GetSymbolFile()->GetObjectFile()->GetModule()->GetTypeList();
416 }
417 
418 const lldb_private::Declaration &
419 lldb_private::Type::GetDeclaration () const
420 {
421     return m_decl;
422 }
423 
424 bool
425 lldb_private::Type::ResolveClangType (bool forward_decl_is_ok)
426 {
427     if (m_clang_type == NULL)
428     {
429         TypeList *type_list = GetTypeList();
430         Type *encoding_type = GetEncodingType();
431 
432         if (encoding_type)
433         {
434             switch (m_encoding_uid_type)
435             {
436             case eEncodingIsUID:
437                 m_clang_type = encoding_type->GetClangType();
438                 break;
439 
440             case eEncodingIsConstUID:
441                 m_clang_type = ClangASTContext::AddConstModifier (encoding_type->GetClangForwardType());
442                 break;
443 
444             case eEncodingIsRestrictUID:
445                 m_clang_type = ClangASTContext::AddRestrictModifier (encoding_type->GetClangForwardType());
446                 break;
447 
448             case eEncodingIsVolatileUID:
449                 m_clang_type = ClangASTContext::AddVolatileModifier (encoding_type->GetClangForwardType());
450                 break;
451 
452             case eEncodingIsTypedefUID:
453                 m_clang_type = type_list->CreateClangTypedefType (this, encoding_type);
454                 // Clear the name so it can get fully qualified in case the
455                 // typedef is in a namespace.
456                 m_name.Clear();
457                 break;
458 
459             case eEncodingIsPointerUID:
460                 m_clang_type = type_list->CreateClangPointerType (encoding_type);
461                 break;
462 
463             case eEncodingIsLValueReferenceUID:
464                 m_clang_type = type_list->CreateClangLValueReferenceType (encoding_type);
465                 break;
466 
467             case eEncodingIsRValueReferenceUID:
468                 m_clang_type = type_list->CreateClangRValueReferenceType (encoding_type);
469                 break;
470 
471             default:
472                 assert(!"Unhandled encoding_data_type.");
473                 break;
474             }
475         }
476         else
477         {
478             // We have no encoding type, return void?
479             clang_type_t void_clang_type = type_list->GetClangASTContext().GetBuiltInType_void();
480             switch (m_encoding_uid_type)
481             {
482             case eEncodingIsUID:
483                 m_clang_type = void_clang_type;
484                 break;
485 
486             case eEncodingIsConstUID:
487                 m_clang_type = ClangASTContext::AddConstModifier (void_clang_type);
488                 break;
489 
490             case eEncodingIsRestrictUID:
491                 m_clang_type = ClangASTContext::AddRestrictModifier (void_clang_type);
492                 break;
493 
494             case eEncodingIsVolatileUID:
495                 m_clang_type = ClangASTContext::AddVolatileModifier (void_clang_type);
496                 break;
497 
498             case eEncodingIsTypedefUID:
499                 m_clang_type = type_list->GetClangASTContext().CreateTypedefType (m_name.AsCString(), void_clang_type, NULL);
500                 break;
501 
502             case eEncodingIsPointerUID:
503                 m_clang_type = type_list->GetClangASTContext().CreatePointerType (void_clang_type);
504                 break;
505 
506             case eEncodingIsLValueReferenceUID:
507                 m_clang_type = type_list->GetClangASTContext().CreateLValueReferenceType (void_clang_type);
508                 break;
509 
510             case eEncodingIsRValueReferenceUID:
511                 m_clang_type = type_list->GetClangASTContext().CreateRValueReferenceType (void_clang_type);
512                 break;
513 
514             default:
515                 assert(!"Unhandled encoding_data_type.");
516                 break;
517             }
518         }
519     }
520 
521     // Check if we have a forward reference to a class/struct/union/enum?
522     if (m_clang_type != NULL &&
523         m_is_forward_decl == true &&
524         forward_decl_is_ok == false)
525     {
526         m_is_forward_decl = false;
527         if (!ClangASTType::IsDefined (m_clang_type))
528         {
529             // We have a forward declaration, we need to resolve it to a complete
530             // definition.
531             m_symbol_file->ResolveClangOpaqueTypeDefinition (m_clang_type);
532         }
533     }
534 
535     // If we have an encoding type, then we need to make sure it is
536     // resolved appropriately.
537     if (m_encoding_type_decl_resolved == false)
538     {
539         if ((forward_decl_is_ok == true  && !m_encoding_type_forward_decl_resolved) ||
540             (forward_decl_is_ok == false))
541         {
542             Type *encoding_type = GetEncodingType ();
543             if (encoding_type != NULL)
544             {
545                 if (encoding_type->ResolveClangType (forward_decl_is_ok))
546                 {
547                     // We have at least resolve the forward declaration for our
548                     // encoding type...
549                     m_encoding_type_forward_decl_resolved = true;
550 
551                     // Check if we fully resolved our encoding type, and if so
552                     // mark it as having been completely resolved.
553                     if (forward_decl_is_ok == false)
554                         m_encoding_type_decl_resolved = true;
555                 }
556             }
557             else
558             {
559                 // We don't have an encoding type, so mark everything as being
560                 // resolved so we don't get into this if statement again
561                 m_encoding_type_decl_resolved = true;
562                 m_encoding_type_forward_decl_resolved = true;
563             }
564         }
565     }
566     return m_clang_type != NULL;
567 }
568 
569 clang_type_t
570 lldb_private::Type::GetChildClangTypeAtIndex
571 (
572     const char *parent_name,
573     uint32_t idx,
574     bool transparent_pointers,
575     bool omit_empty_base_classes,
576     ConstString& name,
577     uint32_t &child_byte_size,
578     int32_t &child_byte_offset,
579     uint32_t &child_bitfield_bit_size,
580     uint32_t &child_bitfield_bit_offset,
581     bool &child_is_base_class
582 )
583 {
584     if (!ResolveClangType())
585         return NULL;
586 
587     std::string name_str;
588     clang_type_t child_qual_type = GetClangASTContext().GetChildClangTypeAtIndex (
589             parent_name,
590             m_clang_type,
591             idx,
592             transparent_pointers,
593             omit_empty_base_classes,
594             name_str,
595             child_byte_size,
596             child_byte_offset,
597             child_bitfield_bit_size,
598             child_bitfield_bit_offset,
599             child_is_base_class);
600 
601     if (child_qual_type)
602     {
603         if (!name_str.empty())
604             name.SetCString(name_str.c_str());
605         else
606             name.Clear();
607     }
608     return child_qual_type;
609 }
610 
611 
612 clang_type_t
613 lldb_private::Type::GetClangType ()
614 {
615     const bool forward_decl_is_ok = false;
616     ResolveClangType(forward_decl_is_ok);
617     return m_clang_type;
618 }
619 
620 clang_type_t
621 lldb_private::Type::GetClangForwardType ()
622 {
623     const bool forward_decl_is_ok = true;
624     ResolveClangType (forward_decl_is_ok);
625     return m_clang_type;
626 }
627 
628 clang::ASTContext *
629 lldb_private::Type::GetClangAST ()
630 {
631     TypeList *type_list = GetTypeList();
632     if (type_list)
633         return type_list->GetClangASTContext().getASTContext();
634     return NULL;
635 }
636 
637 lldb_private::ClangASTContext &
638 lldb_private::Type::GetClangASTContext ()
639 {
640     return GetTypeList()->GetClangASTContext();
641 }
642 
643 int
644 lldb_private::Type::Compare(const Type &a, const Type &b)
645 {
646     // Just compare the UID values for now...
647     lldb::user_id_t a_uid = a.GetID();
648     lldb::user_id_t b_uid = b.GetID();
649     if (a_uid < b_uid)
650         return -1;
651     if (a_uid > b_uid)
652         return 1;
653     return 0;
654 //  if (a.getQualType() == b.getQualType())
655 //      return 0;
656 }
657 
658