Also: lldb_private::TypeSystem has a "SymbolFile *" registered with it:

    virtual SymbolFile *
    GetSymbolFile () const
    {
        return m_sym_file;
    }

    // Returns true if the symbol file changed during the set accessor.
    virtual void
    SetSymbolFile (SymbolFile *sym_file)
    {
        m_sym_file = sym_file;
    }

So it can use the:

bool
SymbolFile::CompleteType (CompilerType &clang_type);

This is what ClangASTContext::CompleteTagDecl() uses:

void
ClangASTContext::CompleteTagDecl (void *baton, clang::TagDecl *decl)
{
    ClangASTContext *ast = (ClangASTContext *)baton;
    SymbolFile *sym_file = ast->GetSymbolFile();
    if (sym_file)
    {
        CompilerType clang_type = GetTypeForDecl (decl);
        if (clang_type)
            sym_file->CompleteType (clang_type);
    }
}


> On Sep 2, 2015, at 3:48 PM, Greg Clayton via lldb-dev 
> <lldb-dev@lists.llvm.org> wrote:
> 
>> 
>> On Sep 2, 2015, at 3:15 PM, Ryan Brown via lldb-dev 
>> <lldb-dev@lists.llvm.org> wrote:
>> 
>> I'm trying to implement a DWARFASTParser for go, and have hit an issue with 
>> fields for structs.
>> As I understand it, DWARFASTParserClang loads minimal type info for structs 
>> at first, and registers the type in SymbolFileDWARF's 
>> m_forward_decl_clang_type_to_die. 
>> Then later when you call type.GetFullCompilerType() it calls back into the 
>> DWARFASTParser to complete the type.
>> 
>> But it seems like the SBValue's in the python API only get Forward types, 
>> and never complete them. For example, I do:
>> var = frame.FindVariable('theStruct')
>> self.assertEqual(2, var.GetNumChildren())
>> 
>> But I get 0 children, because the type is incomplete and there doesn't seem 
>> to be any way to complete it.
>> ValueObject::GetNumChildren goes through 
>> ValueObject::MaybeCalculateCompleteType, which seems promising. But it only 
>> completes the type for objc. 
>> Would a clang variable already have a full type at this point for some 
>> reason? If so, how do I arrange that for go?
>> 
>> Also, TypeSystem has a GetCompleteType method. I don't understand when this 
>> would be called or how I can implement it without a reference to 
>> SymbolFileDWARF.
> 
> The story goes:
> 
> lldb_private::ClangASTContext inherits from lldb_private::TypeSystem so it is 
> the type system. The ClangASTContext also signs up to be a 
> clang::ExternalASTSource so that it can complete types via:
> 
> ClangASTContext::CompleteTagDecl()
> ClangASTContext::CompleteObjCInterfaceDecl()
> 
> ClangASTContext::CompleteTagDecl() completes C and C++ structs, unions and 
> classes.
> 
> ClangASTContext::CompleteObjCInterfaceDecl() completes Objective C stuff.
> 
> The function that actually figures out how many children will be routed 
> through "CompilerType::GetNumChildren(bool)" with code like this:
> 
> size_t
> ValueObjectVariable::CalculateNumChildren()
> {    
>    CompilerType type(GetCompilerType());
> 
>    if (!type.IsValid())
>        return 0;
> 
>    const bool omit_empty_base_classes = true;
>    return type.GetNumChildren(omit_empty_base_classes);
> }
> 
> 
> CompilerType passes the ball back to the TypeSystem class (ClangASTContext 
> in this case):
> 
> uint32_t
> CompilerType::GetNumChildren (bool omit_empty_base_classes) const
> {
>    if (!IsValid())
>        return 0;
>    return m_type_system->GetNumChildren(m_type, omit_empty_base_classes);
> }
> 
> 
> Down in ClangASTContext it does:
> 
> 
> uint32_t
> ClangASTContext::GetNumChildren (void* type, bool omit_empty_base_classes)
> {
>    if (!type)
>        return 0;
> 
>    uint32_t num_children = 0;
>    clang::QualType qual_type(GetQualType(type));
>    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
>    switch (type_class)
>    {
>        ...
>        case clang::Type::Record:
>            if (GetCompleteQualType (getASTContext(), qual_type))
>            {
> 
> 
> 
> 
> So it is a static function named GetCompleteQualType() in ClangASTContext.cpp 
> that completes the type if it needs to:
> 
> 
> static bool
> GetCompleteQualType (clang::ASTContext *ast, clang::QualType qual_type, bool 
> allow_completion = true)
> {
>    const clang::Type::TypeClass type_class = qual_type->getTypeClass();
>    switch (type_class)
>    {
>        ...
>        case clang::Type::Record:
>        case clang::Type::Enum:
>        {
>            const clang::TagType *tag_type = 
> llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr());
>            if (tag_type)
>            {
>                clang::TagDecl *tag_decl = tag_type->getDecl();
>                if (tag_decl)
>                {
>                    if (tag_decl->isCompleteDefinition())
>                        return true;
> 
>                    if (!allow_completion)
>                        return false;
> 
>                    if (tag_decl->hasExternalLexicalStorage())
>                    {
>                        if (ast)
>                        {
>                            clang::ExternalASTSource *external_ast_source = 
> ast->getExternalSource();
>                            if (external_ast_source)
>                            {
>                                external_ast_source->CompleteType(tag_decl);
> 
> 
> 
> So it will ask the clang::ExternalASTSource to complete the type which should 
> call ClangASTContext::CompleteTagDecl() to complete your type.
> 
> So this is how it would work if you used DWARFASTParserClang. Are you using 
> that? Or are you using your own DWARFASTParserGo? If so, then you need to 
> implement this type completion in your own TypeSystem. Your type system 
> subclass is required to implement many different function for type 
> introspection, one of which is:
> 
> class TypeSystem {
> 
>   virtual uint32_t
>    GetNumChildren (void *type, bool omit_empty_base_classes) = 0;
> 
> };
> 
> So the clang version in ClangASTContext::GetNumChildren() knows to complete 
> the type if it a forward declaration. If you have a GoASTContext class that 
> inherits from TypeSystem, then all function that might need to know about the 
> contents of a class or struct, will need to know to complete the type. Or, 
> you can fully parse the structs/unions/classes as you parse the DWARF and not 
> worry about implementing lazy type completion for Go.
> 
> So the main questions I have for you are:
> - Do you have a GoASTContext that inherits from TypeSystem?
> - If you do, in order for DWARF to parse Go types that use the GoASTContext, 
> you will need to write a DWARFASTParser subclass that constructs Go types 
> from DWARF. Then your TypeSystem subclass will need to implement:
> 
> TypeSystem {
> 
>    virtual DWARFASTParser *
>    GetDWARFParser ();
> 
> };
> 
> 
> _______________________________________________
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to