Type.cpp revision bf8e42b9da0e1c6349a727d644ad37610b00d556
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
29using namespace lldb;
30
31lldb_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
60lldb_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
76const lldb_private::Type&
77lldb_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
97void
98lldb_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
137void
138lldb_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
188const lldb_private::ConstString &
189lldb_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
203void
204lldb_private::Type::DumpTypeName(Stream *s)
205{
206    GetName().Dump(s, "<invalid-type-name>");
207}
208
209
210void
211lldb_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
251lldb_private::Type *
252lldb_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
264uint64_t
265lldb_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
300uint32_t
301lldb_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
309bool
310lldb_private::Type::IsAggregateType ()
311{
312    if (ResolveClangType())
313        return ClangASTContext::IsAggregateType (m_clang_type);
314    return false;
315}
316
317lldb::Format
318lldb_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
328lldb::Encoding
329lldb_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
340bool
341lldb_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
366bool
367lldb_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
405bool
406lldb_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
412lldb_private::TypeList*
413lldb_private::Type::GetTypeList()
414{
415    return GetSymbolFile()->GetObjectFile()->GetModule()->GetTypeList();
416}
417
418const lldb_private::Declaration &
419lldb_private::Type::GetDeclaration () const
420{
421    return m_decl;
422}
423
424bool
425lldb_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
569clang_type_t
570lldb_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
612clang_type_t
613lldb_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
620clang_type_t
621lldb_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
628clang::ASTContext *
629lldb_private::Type::GetClangAST ()
630{
631    TypeList *type_list = GetTypeList();
632    if (type_list)
633        return type_list->GetClangASTContext().getASTContext();
634    return NULL;
635}
636
637lldb_private::ClangASTContext &
638lldb_private::Type::GetClangASTContext ()
639{
640    return GetTypeList()->GetClangASTContext();
641}
642
643int
644lldb_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