diff options
author | Greg Clayton <gclayton@apple.com> | 2013-04-05 23:27:21 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2013-04-05 23:27:21 +0000 |
commit | 1c8ef47681ad841ed52e53f2b998a1c9419b653d (patch) | |
tree | 4ff821079c8006ea50c9bdadb0d5085baadb6eeb | |
parent | 05c4d023f3e7f854ef95ffd2b1e1290296154c85 (diff) | |
download | bcm5719-llvm-1c8ef47681ad841ed52e53f2b998a1c9419b653d.tar.gz bcm5719-llvm-1c8ef47681ad841ed52e53f2b998a1c9419b653d.zip |
Added support "__attribute__((__vector_size__(B)))" and "__attribute__((ext_vector_type(N)))".
Now we can:
1 - see the return value for functions that return types that use the "ext_vector_size"
2 - dump values that use the vector attributes ("expr $ymm0")
3 - modified the DWARF parser to correctly parse GNU vector types from the DWARF by turning them into clang::Type::ExtVector types instead of just standard arrays
llvm-svn: 178924
-rw-r--r-- | lldb/include/lldb/Symbol/ClangASTContext.h | 13 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/ClangASTType.h | 4 | ||||
-rw-r--r-- | lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 285 | ||||
-rw-r--r-- | lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h | 2 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h | 1 | ||||
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 35 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 179 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTType.cpp | 6 | ||||
-rw-r--r-- | lldb/test/functionalities/return-value/TestReturnValue.py | 3 | ||||
-rw-r--r-- | lldb/test/functionalities/return-value/call-func.c | 18 |
10 files changed, 356 insertions, 190 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index 1b4dd2b5017..2678af53ac1 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -53,7 +53,11 @@ public: eTypeIsTemplate = (1u << 14), eTypeIsTypedef = (1u << 15), eTypeIsVector = (1u << 16), - eTypeIsScalar = (1u << 17) + eTypeIsScalar = (1u << 17), + eTypeIsInteger = (1u << 18), + eTypeIsFloat = (1u << 19), + eTypeIsComplex = (1u << 20), + eTypeIsSigned = (1u << 21) }; typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); @@ -578,8 +582,8 @@ public: // Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations static uint32_t GetTypeInfo (lldb::clang_type_t clang_type, - clang::ASTContext *ast, // The AST for clang_type (can be NULL) - lldb::clang_type_t *pointee_or_element_type); // (can be NULL) + clang::ASTContext *ast, // The AST for clang_type (can be NULL) + lldb::clang_type_t *pointee_or_element_type); // (can be NULL) static uint32_t GetNumChildren (clang::ASTContext *ast, @@ -800,7 +804,8 @@ public: lldb::clang_type_t CreateArrayType (lldb::clang_type_t element_type, - size_t element_count); + size_t element_count, + bool is_vector); //------------------------------------------------------------------ // Tag Declarations diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index 39a1982b4b9..d2e33a80449 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -110,6 +110,10 @@ public: uint64_t GetClangTypeByteSize (); + static uint64_t + GetClangTypeByteSize (clang::ASTContext *ast_context, + lldb::clang_type_t clang_type); + uint64_t GetClangTypeBitWidth (); diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index fbac6a7a5e5..49058786a9a 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -470,7 +470,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, // For now, assume that the types in the AST values come from the Target's // scratch AST. - clang::ASTContext *ast_context = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext(); + clang::ASTContext *ast = thread.CalculateTarget()->GetScratchClangASTContext()->getASTContext(); // Extract the register context so we can read arguments from registers @@ -522,7 +522,7 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread, if (ClangASTContext::IsIntegerType (value_type, is_signed)) { - size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); + size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, value_type); ReadIntegerArgument(value->GetScalar(), bit_width, @@ -567,8 +567,8 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb return error; } - clang::ASTContext *ast_context = new_value_sp->GetClangAST(); - if (!ast_context) + clang::ASTContext *ast = new_value_sp->GetClangAST(); + if (!ast) { error.SetErrorString ("Null clang AST for return value."); return error; @@ -608,7 +608,7 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb error.SetErrorString ("We don't support returning complex values at present"); else { - size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); + size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, value_type); if (bit_width <= 64) { const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); @@ -645,140 +645,181 @@ ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueOb ValueObjectSP ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread, - ClangASTType &ast_type) const + ClangASTType &ast_type) const { ValueObjectSP return_valobj_sp; Value value; - clang_type_t value_type = ast_type.GetOpaqueQualType(); - if (!value_type) + clang_type_t return_value_type = ast_type.GetOpaqueQualType(); + if (!return_value_type) return return_valobj_sp; - clang::ASTContext *ast_context = ast_type.GetASTContext(); - if (!ast_context) + clang::ASTContext *ast = ast_type.GetASTContext(); + if (!ast) return return_valobj_sp; - value.SetContext (Value::eContextTypeClangType, value_type); + value.SetContext (Value::eContextTypeClangType, return_value_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; - bool is_signed; - bool is_complex; - uint32_t count; - - if (ClangASTContext::IsIntegerType (value_type, is_signed)) + const uint32_t type_flags = ClangASTContext::GetTypeInfo (return_value_type, ast, NULL); + if (type_flags & ClangASTContext::eTypeIsScalar) { - // For now, assume that the types in the AST values come from the Target's - // scratch AST. - - - // Extract the register context so we can read arguments from registers - - size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); - uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); - - switch (bit_width) + value.SetValueType(Value::eValueTypeScalar); + + bool success = false; + if (type_flags & ClangASTContext::eTypeIsInteger) { - default: - case 128: - // Scalar can't hold 128-bit literals, so we don't handle this - return return_valobj_sp; - case 64: - if (is_signed) - value.GetScalar() = (int64_t)(raw_value); - else - value.GetScalar() = (uint64_t)(raw_value); - break; - case 32: - if (is_signed) - value.GetScalar() = (int32_t)(raw_value & 0xffffffff); - else - value.GetScalar() = (uint32_t)(raw_value & 0xffffffff); - break; - case 16: - if (is_signed) - value.GetScalar() = (int16_t)(raw_value & 0xffff); - else - value.GetScalar() = (uint16_t)(raw_value & 0xffff); - break; - case 8: - if (is_signed) - value.GetScalar() = (int8_t)(raw_value & 0xff); - else - value.GetScalar() = (uint8_t)(raw_value & 0xff); - break; + // Extract the register context so we can read arguments from registers + + const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type); + uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0); + const bool is_signed = (type_flags & ClangASTContext::eTypeIsSigned) != 0; + switch (byte_size) + { + default: + break; + + case sizeof(uint64_t): + if (is_signed) + value.GetScalar() = (int64_t)(raw_value); + else + value.GetScalar() = (uint64_t)(raw_value); + success = true; + break; + + case sizeof(uint32_t): + if (is_signed) + value.GetScalar() = (int32_t)(raw_value & UINT32_MAX); + else + value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX); + success = true; + break; + + case sizeof(uint16_t): + if (is_signed) + value.GetScalar() = (int16_t)(raw_value & UINT16_MAX); + else + value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX); + success = true; + break; + + case sizeof(uint8_t): + if (is_signed) + value.GetScalar() = (int8_t)(raw_value & UINT8_MAX); + else + value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX); + success = true; + break; + } } - } - else if (ClangASTContext::IsFloatingPointType(value_type, count, is_complex)) - { - // Don't handle complex yet. - if (is_complex) - return return_valobj_sp; - - size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type); - if (bit_width <= 64) + else if (type_flags & ClangASTContext::eTypeIsFloat) { - const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); - RegisterValue xmm0_value; - if (reg_ctx->ReadRegister (xmm0_info, xmm0_value)) + if (type_flags & ClangASTContext::eTypeIsComplex) { - DataExtractor data; - if (xmm0_value.GetData(data)) + // Don't handle complex yet. + } + else + { + const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type); + if (byte_size <= sizeof(long double)) { - lldb::offset_t offset = 0; - switch (bit_width) + const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0); + RegisterValue xmm0_value; + if (reg_ctx->ReadRegister (xmm0_info, xmm0_value)) { - default: - return return_valobj_sp; - case 32: - value.GetScalar() = (float) data.GetFloat(&offset); - break; - case 64: - value.GetScalar() = (double) data.GetDouble(&offset); - break; + DataExtractor data; + if (xmm0_value.GetData(data)) + { + lldb::offset_t offset = 0; + if (byte_size == sizeof(float)) + { + value.GetScalar() = (float) data.GetFloat(&offset); + success = true; + } + else if (byte_size == sizeof(double)) + { + value.GetScalar() = (double) data.GetDouble(&offset); + success = true; + } + else if (byte_size == sizeof(long double)) + { + // Don't handle long double since that can be encoded as 80 bit floats... + } + } } } } } - else if (bit_width == 128) - { - // FIXME: x86_64 returns long doubles in stmm0, which is in some 80 bit long double - // format, and so we'll have to write some code to convert that into 128 bit long doubles. -// const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("stmm0", 0); -// RegisterValue st0_value; -// if (reg_ctx->ReadRegister (st0_info, st0_value)) -// { -// DataExtractor data; -// if (st0_value.GetData(data)) -// { -// uint32_t offset = 0; -// value.GetScalar() = (long double) data.GetLongDouble (&offset); -// return true; -// } -// } - - return return_valobj_sp; - } + + if (success) + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + ast_type.GetASTContext(), + value, + ConstString("")); + } - else if (ClangASTContext::IsPointerType (value_type)) + else if (type_flags & ClangASTContext::eTypeIsPointer) { unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB]; value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0); + value.SetValueType(Value::eValueTypeScalar); + return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(), + ast_type.GetASTContext(), + value, + ConstString("")); } - else + else if (type_flags & ClangASTContext::eTypeIsVector) { - return return_valobj_sp; + const size_t byte_size = ClangASTType::GetClangTypeByteSize(ast, return_value_type); + if (byte_size > 0) + { + + const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0); + if (altivec_reg == NULL) + { + altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0); + if (altivec_reg == NULL) + altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0); + } + + if (altivec_reg) + { + if (byte_size <= altivec_reg->byte_size) + { + ProcessSP process_sp (thread.GetProcess()); + if (process_sp) + { + std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0)); + const ByteOrder byte_order = process_sp->GetByteOrder(); + RegisterValue reg_value; + if (reg_ctx->ReadRegister(altivec_reg, reg_value)) + { + Error error; + if (reg_value.GetAsMemoryData (altivec_reg, + heap_data_ap->GetBytes(), + heap_data_ap->GetByteSize(), + byte_order, + error)) + { + DataExtractor data (DataBufferSP (heap_data_ap.release()), + byte_order, + process_sp->GetTarget().GetArchitecture().GetAddressByteSize()); + return_valobj_sp = ValueObjectConstResult::Create (&thread, + ast, + return_value_type, + ConstString(""), + data); + } + } + } + } + } + } } - // If we get here, we have a valid Value, so make our ValueObject out of it: - - return_valobj_sp = ValueObjectConstResult::Create( - thread.GetStackFrameAtIndex(0).get(), - ast_type.GetASTContext(), - value, - ConstString("")); return return_valobj_sp; } @@ -792,20 +833,20 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type if (return_valobj_sp) return return_valobj_sp; - clang_type_t ret_value_type = ast_type.GetOpaqueQualType(); - if (!ret_value_type) + clang_type_t return_value_type = ast_type.GetOpaqueQualType(); + if (!return_value_type) return return_valobj_sp; - clang::ASTContext *ast_context = ast_type.GetASTContext(); - if (!ast_context) + clang::ASTContext *ast = ast_type.GetASTContext(); + if (!ast) return return_valobj_sp; RegisterContextSP reg_ctx_sp = thread.GetRegisterContext(); if (!reg_ctx_sp) return return_valobj_sp; - size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, ret_value_type); - if (ClangASTContext::IsAggregateType(ret_value_type)) + size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast, return_value_type); + if (ClangASTContext::IsAggregateType(return_value_type)) { Target *target = exe_ctx.GetTargetPtr(); bool is_memory = true; @@ -838,7 +879,7 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type uint32_t fp_bytes = 0; // Tracks how much of the xmm registers we've consumed so far uint32_t integer_bytes = 0; // Tracks how much of the rax/rds registers we've consumed so far - uint32_t num_children = ClangASTContext::GetNumFields (ast_context, ret_value_type); + uint32_t num_children = ClangASTContext::GetNumFields (ast, return_value_type); // Since we are in the small struct regime, assume we are not in memory. is_memory = false; @@ -851,8 +892,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type bool is_complex; uint32_t count; - clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx, name, &field_bit_offset, NULL, NULL); - size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, field_clang_type); + clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast, return_value_type, idx, name, &field_bit_offset, NULL, NULL); + size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast, field_clang_type); // If there are any unaligned fields, this is stored in memory. if (field_bit_offset % field_bit_width != 0) @@ -934,8 +975,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type else { uint64_t next_field_bit_offset = 0; - clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, - ret_value_type, + clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast, + return_value_type, idx + 1, name, &next_field_bit_offset, @@ -960,8 +1001,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type else { uint64_t prev_field_bit_offset = 0; - clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, - ret_value_type, + clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast, + return_value_type, idx - 1, name, &prev_field_bit_offset, @@ -1031,8 +1072,8 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type { // The result is in our data buffer. Let's make a variable object out of it: return_valobj_sp = ValueObjectConstResult::Create (&thread, - ast_context, - ret_value_type, + ast, + return_value_type, ConstString(""), return_ext); } diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index d0fd38589e6..2cc3fbcca32 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -51,7 +51,7 @@ public: protected: lldb::ValueObjectSP GetReturnValueObjectSimple (lldb_private::Thread &thread, - lldb_private::ClangASTType &ast_type) const; + lldb_private::ClangASTType &ast_type) const; public: virtual lldb::ValueObjectSP diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 751653c7925..4c400b2df58 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -57,6 +57,7 @@ public: uint64_t Reference(const DWARFCompileUnit* cu) const; uint64_t Reference (dw_offset_t offset) const; bool ResolveCompileUnitReferences(const DWARFCompileUnit* cu); + bool Boolean() const { return m_value.value.uval != 0; } uint64_t Unsigned() const { return m_value.value.uval; } void SetUnsigned(uint64_t uval) { m_value.value.uval = uval; } int64_t Signed() const { return m_value.value.sval; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index a15a20871a7..9eea913bd8b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1589,12 +1589,12 @@ SymbolFileDWARF::ParseChildMembers break; case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break; - case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_APPLE_property_name: prop_name = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_APPLE_property_getter: prop_getter_name = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_APPLE_property_setter: prop_setter_name = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break; - case DW_AT_external: is_external = form_value.Unsigned() != 0; break; + case DW_AT_external: is_external = form_value.Boolean(); break; default: case DW_AT_declaration: @@ -1837,7 +1837,7 @@ SymbolFileDWARF::ParseChildMembers MakeUserID(parent_die->GetOffset())); } - member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0); + member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false); } } } @@ -1969,7 +1969,7 @@ SymbolFileDWARF::ParseChildMembers accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break; + case DW_AT_virtuality: is_virtual = form_value.Boolean(); break; default: case DW_AT_sibling: break; @@ -3944,7 +3944,7 @@ SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc, case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break; case DW_AT_name: name = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_type: param_type_die_offset = form_value.Reference(dwarf_cu); break; - case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_location: // if (form_value.BlockData()) // { @@ -5682,7 +5682,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, break; case DW_AT_declaration: - is_forward_declaration = form_value.Unsigned() != 0; + is_forward_declaration = form_value.Boolean(); break; case DW_AT_APPLE_runtime_class: @@ -6041,7 +6041,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_AT_type: encoding_uid = form_value.Reference(dwarf_cu); break; case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; //is_forward_declaration = form_value.Unsigned() != 0; break; + case DW_AT_declaration: break; //is_forward_declaration = form_value.Boolean(); break; case DW_AT_allocated: case DW_AT_associated: case DW_AT_bit_stride: @@ -6159,11 +6159,11 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_AT_MIPS_linkage_name: break; // mangled = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_type: type_die_offset = form_value.Reference(dwarf_cu); break; case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; // is_forward_declaration = form_value.Unsigned() != 0; break; - case DW_AT_inline: is_inline = form_value.Unsigned() != 0; break; - case DW_AT_virtuality: is_virtual = form_value.Unsigned() != 0; break; - case DW_AT_explicit: is_explicit = form_value.Unsigned() != 0; break; - case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break; + case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; + case DW_AT_inline: is_inline = form_value.Boolean(); break; + case DW_AT_virtuality: is_virtual = form_value.Boolean(); break; + case DW_AT_explicit: is_explicit = form_value.Boolean(); break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_external: @@ -6600,6 +6600,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, int64_t first_index = 0; uint32_t byte_stride = 0; uint32_t bit_stride = 0; + bool is_vector = false; const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) @@ -6625,8 +6626,9 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, case DW_AT_byte_size: break; // byte_size = form_value.Unsigned(); break; case DW_AT_byte_stride: byte_stride = form_value.Unsigned(); break; case DW_AT_bit_stride: bit_stride = form_value.Unsigned(); break; + case DW_AT_GNU_vector: is_vector = form_value.Boolean(); break; case DW_AT_accessibility: break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; - case DW_AT_declaration: break; // is_forward_declaration = form_value.Unsigned() != 0; break; + case DW_AT_declaration: break; // is_forward_declaration = form_value.Boolean(); break; case DW_AT_allocated: case DW_AT_associated: case DW_AT_data_location: @@ -6661,7 +6663,8 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, { num_elements = *pos; clang_type = ast.CreateArrayType (array_element_type, - num_elements); + num_elements, + is_vector); array_element_type = clang_type; array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements : array_element_bit_stride; } @@ -7026,7 +7029,7 @@ SymbolFileDWARF::ParseVariableDIE case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break; case DW_AT_type: type_uid = form_value.Reference(dwarf_cu); break; - case DW_AT_external: is_external = form_value.Unsigned() != 0; break; + case DW_AT_external: is_external = form_value.Boolean(); break; case DW_AT_const_value: // If we have already found a DW_AT_location attribute, ignore this attribute. if (!has_explicit_location) @@ -7097,7 +7100,7 @@ SymbolFileDWARF::ParseVariableDIE } break; - case DW_AT_artificial: is_artificial = form_value.Unsigned() != 0; break; + case DW_AT_artificial: is_artificial = form_value.Boolean(); break; case DW_AT_accessibility: break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break; case DW_AT_declaration: case DW_AT_description: diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index 7f8c2ec741c..8d03e93eeb8 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -2918,48 +2918,78 @@ ClangASTContext::GetTypeInfo switch (type_class) { case clang::Type::Builtin: - switch (cast<clang::BuiltinType>(qual_type)->getKind()) { - case clang::BuiltinType::ObjCId: - case clang::BuiltinType::ObjCClass: - if (ast && pointee_or_element_clang_type) - *pointee_or_element_clang_type = ast->ObjCBuiltinClassTy.getAsOpaquePtr(); - return eTypeIsBuiltIn | eTypeIsPointer | eTypeHasValue | eTypeIsObjC; + const BuiltinType *builtin_type = dyn_cast<BuiltinType>(qual_type->getCanonicalTypeInternal()); + + uint32_t builtin_type_flags = eTypeIsBuiltIn | eTypeHasValue; + switch (builtin_type->getKind()) + { + case clang::BuiltinType::ObjCId: + case clang::BuiltinType::ObjCClass: + if (ast && pointee_or_element_clang_type) + *pointee_or_element_clang_type = ast->ObjCBuiltinClassTy.getAsOpaquePtr(); + builtin_type_flags |= eTypeIsPointer | eTypeIsObjC; break; - case clang::BuiltinType::Bool: - case clang::BuiltinType::Char_U: - case clang::BuiltinType::UChar: - case clang::BuiltinType::WChar_U: - case clang::BuiltinType::Char16: - case clang::BuiltinType::Char32: - case clang::BuiltinType::UShort: - case clang::BuiltinType::UInt: - case clang::BuiltinType::ULong: - case clang::BuiltinType::ULongLong: - case clang::BuiltinType::UInt128: - case clang::BuiltinType::Char_S: - case clang::BuiltinType::SChar: - case clang::BuiltinType::WChar_S: - case clang::BuiltinType::Short: - case clang::BuiltinType::Int: - case clang::BuiltinType::Long: - case clang::BuiltinType::LongLong: - case clang::BuiltinType::Int128: - case clang::BuiltinType::Float: - case clang::BuiltinType::Double: - case clang::BuiltinType::LongDouble: - return eTypeIsBuiltIn | eTypeHasValue | eTypeIsScalar; - default: - break; + + case clang::BuiltinType::ObjCSel: + case clang::BuiltinType::Bool: + case clang::BuiltinType::Char_U: + case clang::BuiltinType::UChar: + case clang::BuiltinType::WChar_U: + case clang::BuiltinType::Char16: + case clang::BuiltinType::Char32: + case clang::BuiltinType::UShort: + case clang::BuiltinType::UInt: + case clang::BuiltinType::ULong: + case clang::BuiltinType::ULongLong: + case clang::BuiltinType::UInt128: + case clang::BuiltinType::Char_S: + case clang::BuiltinType::SChar: + case clang::BuiltinType::WChar_S: + case clang::BuiltinType::Short: + case clang::BuiltinType::Int: + case clang::BuiltinType::Long: + case clang::BuiltinType::LongLong: + case clang::BuiltinType::Int128: + case clang::BuiltinType::Float: + case clang::BuiltinType::Double: + case clang::BuiltinType::LongDouble: + builtin_type_flags |= eTypeIsScalar; + if (builtin_type->isInteger()) + { + builtin_type_flags |= eTypeIsInteger; + if (builtin_type->isSignedInteger()) + builtin_type_flags |= eTypeIsSigned; + } + else if (builtin_type->isFloatingPoint()) + builtin_type_flags |= eTypeIsFloat; + break; + default: + break; + } + return builtin_type_flags; } - return eTypeIsBuiltIn | eTypeHasValue; - case clang::Type::BlockPointer: + case clang::Type::BlockPointer: if (pointee_or_element_clang_type) *pointee_or_element_clang_type = qual_type->getPointeeType().getAsOpaquePtr(); return eTypeIsPointer | eTypeHasChildren | eTypeIsBlock; - case clang::Type::Complex: return eTypeIsBuiltIn | eTypeHasValue; + case clang::Type::Complex: + { + uint32_t complex_type_flags = eTypeIsBuiltIn | eTypeHasValue | eTypeIsComplex; + const ComplexType *complex_type = dyn_cast<ComplexType>(qual_type->getCanonicalTypeInternal()); + if (complex_type) + { + QualType complex_element_type (complex_type->getElementType()); + if (complex_element_type->isIntegerType()) + complex_type_flags |= eTypeIsFloat; + else if (complex_element_type->isFloatingType()) + complex_type_flags |= eTypeIsInteger; + } + return complex_type_flags; + } + break; case clang::Type::ConstantArray: case clang::Type::DependentSizedArray: @@ -2983,7 +3013,6 @@ ClangASTContext::GetTypeInfo return ClangASTContext::GetTypeInfo (cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), ast, pointee_or_element_clang_type); - case clang::Type::ExtVector: return eTypeHasChildren | eTypeIsVector; case clang::Type::FunctionProto: return eTypeIsFuncPrototype | eTypeHasValue; case clang::Type::FunctionNoProto: return eTypeIsFuncPrototype | eTypeHasValue; case clang::Type::InjectedClassName: return 0; @@ -3027,7 +3056,21 @@ ClangASTContext::GetTypeInfo case clang::Type::TypeOfExpr: return 0; case clang::Type::TypeOf: return 0; case clang::Type::UnresolvedUsing: return 0; - case clang::Type::Vector: return eTypeHasChildren | eTypeIsVector; + + case clang::Type::ExtVector: + case clang::Type::Vector: + { + uint32_t vector_type_flags = eTypeHasChildren | eTypeIsVector; + const VectorType *vector_type = dyn_cast<VectorType>(qual_type->getCanonicalTypeInternal()); + if (vector_type) + { + if (vector_type->isIntegerType()) + vector_type_flags |= eTypeIsFloat; + else if (vector_type->isFloatingType()) + vector_type_flags |= eTypeIsInteger; + } + return vector_type_flags; + } default: return 0; } return 0; @@ -3182,6 +3225,11 @@ ClangASTContext::GetNumChildren (clang::ASTContext *ast, clang_type_t clang_type } break; + case clang::Type::Vector: + case clang::Type::ExtVector: + num_children = cast<VectorType>(qual_type.getTypePtr())->getNumElements(); + break; + case clang::Type::ConstantArray: num_children = cast<ConstantArrayType>(qual_type.getTypePtr())->getSize().getLimitedValue(); break; @@ -4211,6 +4259,30 @@ ClangASTContext::GetChildClangTypeAtIndex } break; + case clang::Type::Vector: + case clang::Type::ExtVector: + if (idx_is_valid) + { + const VectorType *array = cast<VectorType>(parent_qual_type.getTypePtr()); + if (array) + { + if (GetCompleteQualType (ast, array->getElementType())) + { + std::pair<uint64_t, unsigned> field_type_info = ast->getTypeInfo(array->getElementType()); + + char element_name[64]; + ::snprintf (element_name, sizeof (element_name), "[%zu]", idx); + + child_name.assign(element_name); + assert(field_type_info.first % 8 == 0); + child_byte_size = field_type_info.first / 8; + child_byte_offset = (int32_t)idx * (int32_t)child_byte_size; + return array->getElementType().getAsOpaquePtr(); + } + } + } + break; + case clang::Type::ConstantArray: case clang::Type::IncompleteArray: if (ignore_array_bounds || idx_is_valid) @@ -5335,26 +5407,39 @@ ClangASTContext::SetFunctionParameters (FunctionDecl *function_decl, ParmVarDecl #pragma mark Array Types clang_type_t -ClangASTContext::CreateArrayType (clang_type_t element_type, size_t element_count) +ClangASTContext::CreateArrayType (clang_type_t element_type, + size_t element_count, + bool is_vector) { if (element_type) { ASTContext *ast = getASTContext(); assert (ast != NULL); - llvm::APInt ap_element_count (64, element_count); - if (element_count == 0) - { - return ast->getIncompleteArrayType(QualType::getFromOpaquePtr(element_type), - ArrayType::Normal, - 0).getAsOpaquePtr(); + QualType element_qual_type(QualType::getFromOpaquePtr(element_type)); + + if (is_vector) + { + return ast->getExtVectorType(element_qual_type, element_count).getAsOpaquePtr(); } else { - return ast->getConstantArrayType(QualType::getFromOpaquePtr(element_type), - ap_element_count, - ArrayType::Normal, - 0).getAsOpaquePtr(); // ElemQuals + + llvm::APInt ap_element_count (64, element_count); + if (element_count == 0) + { + return ast->getIncompleteArrayType(element_qual_type, + ArrayType::Normal, + 0).getAsOpaquePtr(); + + } + else + { + return ast->getConstantArrayType(element_qual_type, + ap_element_count, + ArrayType::Normal, + 0).getAsOpaquePtr(); // ElemQuals + } } } return NULL; diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index 04ba032f4c1..16e0d488e86 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -1227,6 +1227,12 @@ ClangASTType::GetClangTypeByteSize () } uint64_t +ClangASTType::GetClangTypeByteSize (clang::ASTContext *ast_context, clang_type_t clang_type) +{ + return (GetClangTypeBitWidth (ast_context, clang_type) + 7) / 8; +} + +uint64_t ClangASTType::GetClangTypeBitWidth () { return GetClangTypeBitWidth (m_ast, m_type); diff --git a/lldb/test/functionalities/return-value/TestReturnValue.py b/lldb/test/functionalities/return-value/TestReturnValue.py index 0559cba3354..f5673e24dad 100644 --- a/lldb/test/functionalities/return-value/TestReturnValue.py +++ b/lldb/test/functionalities/return-value/TestReturnValue.py @@ -211,6 +211,9 @@ class ReturnValueTestCase(TestBase): #self.return_and_test_struct_value ("return_one_int_one_double_packed") self.return_and_test_struct_value ("return_one_int_one_long") + self.return_and_test_struct_value ("return_vector_size_float32") + self.return_and_test_struct_value ("return_ext_vector_size_float32") + if __name__ == '__main__': import atexit diff --git a/lldb/test/functionalities/return-value/call-func.c b/lldb/test/functionalities/return-value/call-func.c index f1a411ec429..c7c68d5b977 100644 --- a/lldb/test/functionalities/return-value/call-func.c +++ b/lldb/test/functionalities/return-value/call-func.c @@ -301,6 +301,21 @@ return_one_int_one_pointer (struct one_int_one_pointer value) return value; } +typedef float vector_size_float32 __attribute__((__vector_size__(16))); +typedef float ext_vector_size_float32 __attribute__((ext_vector_type(4))); + +vector_size_float32 +return_vector_size_float32 (vector_size_float32 value) +{ + return value; +} + +ext_vector_size_float32 +return_ext_vector_size_float32 (ext_vector_size_float32 value) +{ + return value; +} + int main () { @@ -351,6 +366,9 @@ main () return_one_int_one_double_packed ((struct one_int_one_double_packed) {10, 20.0}); return_one_int_one_long ((struct one_int_one_long) {10, 20}); + return_vector_size_float32 (( vector_size_float32 ){1.5, 2.25, 4.125, 8.0625}); + return_ext_vector_size_float32 ((ext_vector_size_float32){ 16.5, 32.25, 64.125, 128.0625}); + return 0; } |