void
DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index,
                                      std::vector<uint64_t> &element_orders, uint32_t &byte_stride,
                                      uint32_t &bit_stride)
{
    if (!parent_die)
        return;

    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        const dw_tag_t tag = die.Tag();
        switch (tag)
        {
            case DW_TAG_subrange_type:
            {
                DWARFAttributes attributes;
                const size_t num_child_attributes = die.GetAttributes(attributes);
                if (num_child_attributes > 0)
                {
                    uint64_t num_elements = 0;
                    uint32_t i;
                    for (i = 0; i < num_child_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_count:
                                    num_elements = form_value.Unsigned();
                                    break;

                                default:
                                case DW_AT_type:
                                    break;
                            }
                        }
                    }

                    element_orders.push_back(num_elements);
                }
            }
            break;
        }
    }
}
size_t
DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type)
{
    size_t count = 0;
    uint32_t member_idx = 0;

    ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule();
    GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem());
    if (ast == nullptr)
        return 0;

    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        dw_tag_t tag = die.Tag();

        switch (tag)
        {
            case DW_TAG_member:
            {
                DWARFAttributes attributes;
                const size_t num_attributes = die.GetAttributes(attributes);
                if (num_attributes > 0)
                {
                    Declaration decl;
                    const char *name = NULL;

                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
                    uint32_t member_byte_offset = UINT32_MAX;
                    uint32_t i;
                    for (i = 0; i < num_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_name:
                                    name = form_value.AsCString();
                                    break;
                                case DW_AT_type:
                                    encoding_uid = form_value.Reference();
                                    break;
                                case DW_AT_data_member_location:
                                    if (form_value.BlockData())
                                    {
                                        Value initialValue(0);
                                        Value memberOffset(0);
                                        const DWARFDataExtractor &debug_info_data =
                                            die.GetDWARF()->get_debug_info_data();
                                        uint32_t block_length = form_value.Unsigned();
                                        uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
                                        if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
                                                                      NULL, // ClangExpressionVariableList *
                                                                      NULL, // ClangExpressionDeclMap *
                                                                      NULL, // RegisterContext *
                                                                      module_sp, debug_info_data, die.GetCU(),
                                                                      block_offset, block_length, eRegisterKindDWARF,
                                                                      &initialValue, NULL, memberOffset, NULL))
                                        {
                                            member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
                                        }
                                    }
                                    else
                                    {
                                        // With DWARF 3 and later, if the value is an integer constant,
                                        // this form value is the offset in bytes from the beginning
                                        // of the containing entity.
                                        member_byte_offset = form_value.Unsigned();
                                    }
                                    break;

                                default:
                                    break;
                            }
                        }
                    }

                    Type *member_type = die.ResolveTypeUID(encoding_uid);
                    if (member_type)
                    {
                        CompilerType member_go_type = member_type->GetFullCompilerType();
                        ConstString name_const_str(name);
                        m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset);
                    }
                }
                ++member_idx;
            }
            break;

            default:
                break;
        }
    }

    return count;
}
TypeSP
DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die)
{
    SymbolFileDWARF *dwarf = die.GetDWARF();
    dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED;

    ConstString linkage_name;
    DWARFFormValue type_attr_value;
    lldb::addr_t data_offset = LLDB_INVALID_ADDRESS;
    DWARFExpression length_expression(die.GetCU());

    DWARFAttributes attributes;
    const size_t num_attributes = die.GetAttributes(attributes);
    for (uint32_t i = 0; i < num_attributes; ++i)
    {
        DWARFFormValue form_value;
        dw_attr_t attr = attributes.AttributeAtIndex(i);
        if (attributes.ExtractFormValueAtIndex(i, form_value))
        {
            switch (attr)
            {
                case DW_AT_linkage_name:
                    linkage_name.SetCString(form_value.AsCString());
                    break;
                case DW_AT_type:
                    type_attr_value = form_value;
                    break;
                case DW_AT_data_member_location:
                    data_offset = form_value.Unsigned();
                    break;
                case DW_AT_declaration:
                    break;
                default:
                    assert(false && "Unsupported attribute for DW_TAG_array_type");
            }
        }
    }

    for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); child_die = child_die.GetSibling())
    {
        if (child_die.Tag() == DW_TAG_subrange_type)
        {
            DWARFAttributes attributes;
            const size_t num_attributes = child_die.GetAttributes(attributes);
            for (uint32_t i = 0; i < num_attributes; ++i)
            {
                DWARFFormValue form_value;
                dw_attr_t attr = attributes.AttributeAtIndex(i);
                if (attributes.ExtractFormValueAtIndex(i, form_value))
                {
                    switch (attr)
                    {
                        case DW_AT_count:
                            if (form_value.BlockData())
                                length_expression.CopyOpcodeData(form_value.BlockData(), form_value.Unsigned(),
                                                                 child_die.GetCU()->GetByteOrder(),
                                                                 child_die.GetCU()->GetAddressByteSize());
                            break;
                        default:
                            assert(false && "Unsupported attribute for DW_TAG_subrange_type");
                    }
                }
            }
        }
        else
        {
            assert(false && "Unsupported child for DW_TAG_array_type");
        }
    }

    DIERef type_die_ref(type_attr_value);
    Type *element_type = dwarf->ResolveTypeUID(type_die_ref);
    if (!element_type)
        return nullptr;

    CompilerType element_compiler_type = element_type->GetForwardCompilerType();
    CompilerType array_compiler_type =
        m_ast.CreateArrayType(element_compiler_type, length_expression, data_offset);

    Declaration decl;
    TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr,
                            type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl,
                            array_compiler_type, Type::eResolveStateFull));
    type_sp->SetEncodingType(element_type);
    return type_sp;
}
size_t
DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc,

                                       const DWARFDIE &parent_die, bool &is_variadic,
                                       std::vector<CompilerType> &function_param_types)
{
    if (!parent_die)
        return 0;

    size_t arg_idx = 0;
    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {

        dw_tag_t tag = die.Tag();
        switch (tag)
        {
            case DW_TAG_formal_parameter:
            {
                DWARFAttributes attributes;
                const size_t num_attributes = die.GetAttributes(attributes);
                if (num_attributes > 0)
                {
                    Declaration decl;
                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;

                    uint32_t i;
                    for (i = 0; i < num_attributes; ++i)
                    {
                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
                        DWARFFormValue form_value;
                        if (attributes.ExtractFormValueAtIndex(i, form_value))
                        {
                            switch (attr)
                            {
                                case DW_AT_name:
                                    // = form_value.AsCString();
                                    break;
                                case DW_AT_type:
                                    param_type_die_offset = form_value.Reference();
                                    break;
                                case DW_AT_location:
                                //                          if (form_value.BlockData())
                                //                          {
                                //                              const DWARFDataExtractor& debug_info_data =
                                //                              debug_info();
                                //                              uint32_t block_length = form_value.Unsigned();
                                //                              DWARFDataExtractor location(debug_info_data,
                                //                              form_value.BlockData() - debug_info_data.GetDataStart(),
                                //                              block_length);
                                //                          }
                                //                          else
                                //                          {
                                //                          }
                                //                          break;
                                default:
                                    break;
                            }
                        }
                    }

                    Type *type = parent_die.ResolveTypeUID(param_type_die_offset);
                    if (type)
                    {
                        function_param_types.push_back(type->GetForwardCompilerType());
                    }
                }
                arg_idx++;
            }
            break;

            case DW_TAG_unspecified_parameters:
                is_variadic = true;
                break;

            default:
                break;
        }
    }
    return arg_idx;
}
void
DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die, CompilerType &compiler_type)
{
    DWARFCompileUnit *dwarf_cu = parent_die.GetCU();
    for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling())
    {
        switch (die.Tag())
        {
            case DW_TAG_member:
            {
                const char *name = nullptr;
                DWARFFormValue encoding_uid;
                uint32_t member_byte_offset = UINT32_MAX;
                DWARFExpression member_location_expression(dwarf_cu);
                bool artificial = true;

                DWARFAttributes attributes;
                size_t num_attributes = die.GetAttributes(attributes);
                for (size_t i = 0; i < num_attributes; ++i)
                {
                    DWARFFormValue form_value;
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                    {
                        switch (attributes.AttributeAtIndex(i))
                        {
                            case DW_AT_name:
                                name = form_value.AsCString();
                                break;
                            case DW_AT_type:
                                encoding_uid = form_value;
                                break;
                            case DW_AT_data_member_location:
                                if (form_value.BlockData())
                                    member_location_expression.CopyOpcodeData(
                                        form_value.BlockData(), form_value.Unsigned(), dwarf_cu->GetByteOrder(),
                                        dwarf_cu->GetAddressByteSize());
                                else
                                    member_byte_offset = form_value.Unsigned();
                                break;
                            case DW_AT_artificial:
                                artificial = form_value.Boolean();
                                break;
                            case DW_AT_accessibility:
                                // TODO: Handle when needed
                                break;
                            default:
                                assert(false && "Unhandled attribute for DW_TAG_member");
                                break;
                        }
                    }
                }

                if (strcmp(name, ".dynamic_type") == 0)
                    m_ast.SetDynamicTypeId(compiler_type, member_location_expression);
                else
                {
                    if (Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)))
                        m_ast.AddMemberToObject(compiler_type, ConstString(name), member_type->GetFullCompilerType(),
                                                member_byte_offset);
                }
                break;
            }
            case DW_TAG_inheritance:
            {
                DWARFFormValue encoding_uid;
                uint32_t member_byte_offset = UINT32_MAX;

                DWARFAttributes attributes;
                size_t num_attributes = die.GetAttributes(attributes);
                for (size_t i = 0; i < num_attributes; ++i)
                {
                    DWARFFormValue form_value;
                    if (attributes.ExtractFormValueAtIndex(i, form_value))
                    {
                        switch (attributes.AttributeAtIndex(i))
                        {
                            case DW_AT_type:
                                encoding_uid = form_value;
                                break;
                            case DW_AT_data_member_location:
                                member_byte_offset = form_value.Unsigned();
                                break;
                            case DW_AT_accessibility:
                                // In java all base class is public so we can ignore this attribute
                                break;
                            default:
                                assert(false && "Unhandled attribute for DW_TAG_member");
                                break;
                        }
                    }
                }
                if (Type *base_type = die.ResolveTypeUID(DIERef(encoding_uid)))
                    m_ast.AddBaseClassToObject(compiler_type, base_type->GetFullCompilerType(), member_byte_offset);
                break;
            }
            default:
                break;
        }
    }
}