* [RFC PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) @ 2007-11-12 13:39 Jakub Jelinek 2007-11-16 11:58 ` [PATCH] " Jakub Jelinek 0 siblings, 1 reply; 11+ messages in thread From: Jakub Jelinek @ 2007-11-12 13:39 UTC (permalink / raw) To: gcc-patches, fortran; +Cc: Jan Kratochvil, Daniel Jacobowitz [-- Attachment #1: Type: text/plain, Size: 4534 bytes --] Hi! gfortran since my last patch at least emits useful debug info for normal multi-dimensional arrays and arrays with lower bound different than 0, including I believe assumed size arrays. But it doesn't handle assumed shape arrays, allocatable and pointer arrays that use descriptors. For these DWARF3 has quite detailed example how can they be efficiently described in D.2.1. The following patch tries to implement that. I chose to use a langhook, because this would be terribly hard to express in a generic way, we'd need new tree types for that and, as we want to describe it using the DW_push_object_address magic, quite cumbersome. Say for `vary' two dimensional assumed shape argument gfortran with this patch emits something like below. DW_OP_push_object_address will insert an address of the variable of that type, assumed shape argument is a pointer (reference) to the descriptor structure, so we compute: (*vary)->data + ((*vary)->offset + (*vary)->dim[0].stride * (*vary)->dim[0].lower_bound + (*vary)->dim[1].stride * (*vary)->dim[1].lower_bound) * sizeof (element_type) to get at the actual data location (address of vary(low0, low1)). The addition of stride multiplied lower bounds is needed because gfortran's data + offset * sizeof (element_type) points to vary (0, 0) rather than field with all indexes equal to lower bounds. .uleb128 0xe # (DIE (0x254) DW_TAG_array_type) .byte 0x17 # DW_AT_data_location .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x6 # DW_OP_deref .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x8 .byte 0x6 # DW_OP_deref .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x18 .byte 0x6 # DW_OP_deref .byte 0x22 # DW_OP_plus .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x30 .byte 0x6 # DW_OP_deref .byte 0x22 # DW_OP_plus .byte 0x34 # DW_OP_lit4 .byte 0x1e # DW_OP_mul .byte 0x22 # DW_OP_plus .long 0x14c # DW_AT_type .long 0x2a0 # DW_AT_sibling .uleb128 0xa # (DIE (0x275) DW_TAG_subrange_type) .byte 0x5 # DW_AT_lower_bound .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x20 .byte 0x6 # DW_OP_deref .byte 0x5 # DW_AT_upper_bound .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x28 .byte 0x6 # DW_OP_deref .byte 0x7 # DW_AT_byte_stride .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x18 .byte 0x6 # DW_OP_deref .byte 0x34 # DW_OP_lit4 .byte 0x1e # DW_OP_mul .uleb128 0xa # (DIE (0x28a) DW_TAG_subrange_type) .byte 0x5 # DW_AT_lower_bound .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x38 .byte 0x6 # DW_OP_deref .byte 0x5 # DW_AT_upper_bound .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x40 .byte 0x6 # DW_OP_deref .byte 0x7 # DW_AT_byte_stride .byte 0x97 # DW_OP_push_object_address .byte 0x6 # DW_OP_deref .byte 0x23 # DW_OP_plus_uconst .uleb128 0x30 .byte 0x6 # DW_OP_deref .byte 0x34 # DW_OP_lit4 .byte 0x1e # DW_OP_mul gdb doesn't unfortunately support several constructs used there, Jan made a patch for preliminary DW_OP_push_object_address support over this weekend at least, but e.g. strides aren't supported at all. So I'd just appreciate if anybody could either eyeball this to verify its correct, or try it with some debugger that already supports both DW_OP_push_object_address and DW_OP_byte_stride to verify it. Jakub [-- Attachment #2: Z40b --] [-- Type: text/plain, Size: 16663 bytes --] 2007-11-12 Jakub Jelinek <jakub@redhat.com> PR fortran/22244 * langhooks-def.h (LANG_HOOKS_GET_ARRAY_DESCR_INFO): Define. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add it. * langhooks.h (struct array_descr_info): Forward declaration. (struct lang_hooks_for_types): Add get_array_descr_info field. * dwarf2.h (DW_AT_bit_stride, DW_AT_byte_stride): New. (DW_AT_stride_size, DW_AT_stride): Keep around for Dwarf2 compatibility. * dwarf2out.h (struct array_descr_info): New type. * dwarf2out.c (dwarf_attr_name): Rename DW_AT_stride to DW_AT_byte_stride and DW_AT_stride_size to DW_AT_bit_size. (descr_info_loc, add_descr_info_field, gen_descr_array_type_die): New functions. (gen_type_die_with_usage): Call lang_hooks.types.get_array_descr_info and gen_descr_array_type_die. * trans.h (struct array_descr_info): Forward declaration. (gfc_get_array_descr_info): New prototype. * trans-types.c: Include dwarf2out.h. (gfc_get_array_descr_info): New function. * Make-lang.in (fortran/trans-types.o): Depend on dwarf2out.h. * f95-lang.c (LANG_HOOKS_GET_ARRAY_DESCR_INFO): Define. --- gcc/fortran/trans.h.jj 2007-10-08 10:45:01.000000000 +0200 +++ gcc/fortran/trans.h 2007-11-09 21:35:05.000000000 +0100 @@ -483,6 +483,8 @@ tree poplevel (int, int, int); tree getdecls (void); tree gfc_truthvalue_conversion (tree); tree gfc_builtin_function (tree); +struct array_descr_info; +bool gfc_get_array_descr_info (const_tree, struct array_descr_info *); /* In trans-openmp.c */ bool gfc_omp_privatize_by_reference (const_tree); --- gcc/fortran/trans-types.c.jj 2007-11-05 09:05:44.000000000 +0100 +++ gcc/fortran/trans-types.c 2007-11-10 01:02:44.000000000 +0100 @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. #include "trans-const.h" #include "real.h" #include "flags.h" +#include "dwarf2out.h" \f #if (GFC_MAX_DIMENSIONS < 10) @@ -2121,4 +2122,107 @@ gfc_type_for_mode (enum machine_mode mod return NULL_TREE; } +/* Return TRUE if TYPE is a type with a hidden descriptor, fill in INFO + in that case. */ + +bool +gfc_get_array_descr_info (const_tree type, struct array_descr_info *info) +{ + int rank, dim; + bool indirect = false; + tree etype, ptype, field, t, off_total, base_decl; + tree data_off, offset_off, dim_off, dim_size, elem_size; + tree lower_suboff, upper_suboff, stride_suboff; + + if (! GFC_DESCRIPTOR_TYPE_P (type)) + { + if (! POINTER_TYPE_P (type)) + return false; + type = TREE_TYPE (type); + if (! GFC_DESCRIPTOR_TYPE_P (type)) + return false; + indirect = true; + } + + rank = GFC_TYPE_ARRAY_RANK (type); + if (rank >= (int) (sizeof (info->dimen) / sizeof (info->dimen[0]))) + return false; + + etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type); + gcc_assert (POINTER_TYPE_P (etype)); + etype = TREE_TYPE (etype); + gcc_assert (TREE_CODE (etype) == ARRAY_TYPE); + etype = TREE_TYPE (etype); + if (int_size_in_bytes (etype) <= 0) + return false; + + memset (info, '\0', sizeof (*info)); + info->ndimensions = rank; + info->element_type = etype; + ptype = build_pointer_type (gfc_array_index_type); + if (indirect) + { + info->base_decl = build_decl (VAR_DECL, NULL_TREE, + build_pointer_type (ptype)); + base_decl = build1 (INDIRECT_REF, ptype, info->base_decl); + } + else + info->base_decl = base_decl = build_decl (VAR_DECL, NULL_TREE, ptype); + + elem_size = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (etype)); + field = TYPE_FIELDS (TYPE_MAIN_VARIANT (type)); + data_off = byte_position (field); + field = TREE_CHAIN (field); + offset_off = byte_position (field); + field = TREE_CHAIN (field); + field = TREE_CHAIN (field); + dim_off = byte_position (field); + dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field))); + field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (field))); + stride_suboff = byte_position (field); + field = TREE_CHAIN (field); + lower_suboff = byte_position (field); + field = TREE_CHAIN (field); + upper_suboff = byte_position (field); + + t = base_decl; + if (!integer_zerop (data_off)) + t = build2 (POINTER_PLUS_EXPR, ptype, t, data_off); + t = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), t); + info->data_location = build1 (INDIRECT_REF, ptr_type_node, t); + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, offset_off); + off_total = build1 (INDIRECT_REF, gfc_array_index_type, t); + + for (dim = 0; dim < rank; dim++) + { + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, lower_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + info->dimen[dim].lower_bound = t; + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, upper_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + info->dimen[dim].upper_bound = t; + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, stride_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + off_total = build2 (PLUS_EXPR, gfc_array_index_type, off_total, t); + t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size); + info->dimen[dim].stride = t; + dim_off = size_binop (PLUS_EXPR, dim_off, dim_size); + } + + /* DWARF3 expects to use + data_location + (index0 - low0) * stride0 + (index1 - low1) * stride1 ... + but gfortran uses: + d.data + d.offset * sizeof (elem) + + index0 * d.dim[0].stride * sizeof (elem) + + index1 * d.dim[1].stride * sizeof (elem). */ + off_total = build2 (MULT_EXPR, gfc_array_index_type, off_total, elem_size); + info->data_location = build2 (POINTER_PLUS_EXPR, ptr_type_node, + info->data_location, + fold_convert (sizetype, off_total)); + return true; +} + #include "gt-fortran-trans-types.h" --- gcc/fortran/Make-lang.in.jj 2007-10-08 10:45:01.000000000 +0200 +++ gcc/fortran/Make-lang.in 2007-11-09 22:01:34.000000000 +0100 @@ -312,7 +312,7 @@ fortran/trans-decl.o: $(GFORTRAN_TRANS_D $(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(TREE_GIMPLE_H) \ $(TREE_DUMP_H) fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \ - $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) + $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS) fortran/trans-expr.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h fortran/trans-stmt.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h --- gcc/fortran/f95-lang.c.jj 2007-09-14 11:54:35.000000000 +0200 +++ gcc/fortran/f95-lang.c 2007-11-09 21:33:18.000000000 +0100 @@ -120,6 +120,7 @@ static alias_set_type gfc_get_alias_set #undef LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE #undef LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES #undef LANG_HOOKS_BUILTIN_FUNCTION +#undef LANG_HOOKS_GET_ARRAY_DESCR_INFO /* Define lang hooks. */ #define LANG_HOOKS_NAME "GNU F95" @@ -143,6 +144,7 @@ static alias_set_type gfc_get_alias_set #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \ gfc_omp_firstprivatize_type_sizes #define LANG_HOOKS_BUILTIN_FUNCTION gfc_builtin_function +#define LANG_HOOKS_GET_ARRAY_DESCR_INFO gfc_get_array_descr_info const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; --- gcc/langhooks-def.h.jj 2007-11-02 19:02:47.000000000 +0100 +++ gcc/langhooks-def.h 2007-11-09 17:39:23.000000000 +0100 @@ -180,6 +180,7 @@ extern tree lhd_make_node (enum tree_cod #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \ lhd_omp_firstprivatize_type_sizes #define LANG_HOOKS_TYPE_HASH_EQ NULL +#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL #define LANG_HOOKS_HASH_TYPES true #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \ @@ -193,6 +194,7 @@ extern tree lhd_make_node (enum tree_cod LANG_HOOKS_TYPE_MAX_SIZE, \ LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \ LANG_HOOKS_TYPE_HASH_EQ, \ + LANG_HOOKS_GET_ARRAY_DESCR_INFO, \ LANG_HOOKS_HASH_TYPES \ } --- gcc/dwarf2out.c.jj 2007-11-09 14:29:04.000000000 +0100 +++ gcc/dwarf2out.c 2007-11-10 00:40:24.000000000 +0100 @@ -4263,6 +4263,7 @@ static tree member_declared_type (const_ static const char *decl_start_label (tree); #endif static void gen_array_type_die (tree, dw_die_ref); +static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_ref); #if 0 static void gen_entry_point_die (tree, dw_die_ref); #endif @@ -4669,8 +4670,8 @@ dwarf_attr_name (unsigned int attr) return "DW_AT_return_addr"; case DW_AT_start_scope: return "DW_AT_start_scope"; - case DW_AT_stride_size: - return "DW_AT_stride_size"; + case DW_AT_bit_stride: + return "DW_AT_bit_stride"; case DW_AT_upper_bound: return "DW_AT_upper_bound"; case DW_AT_abstract_origin: @@ -4738,8 +4739,8 @@ dwarf_attr_name (unsigned int attr) return "DW_AT_associated"; case DW_AT_data_location: return "DW_AT_data_location"; - case DW_AT_stride: - return "DW_AT_stride"; + case DW_AT_byte_stride: + return "DW_AT_byte_stride"; case DW_AT_entry_pc: return "DW_AT_entry_pc"; case DW_AT_use_UTF8: @@ -11695,6 +11696,151 @@ gen_array_type_die (tree type, dw_die_re add_pubtype (type, array_die); } +static dw_loc_descr_ref +descr_info_loc (tree val, tree base_decl) +{ + HOST_WIDE_INT size; + dw_loc_descr_ref loc, loc2; + + if (val == base_decl) + return new_loc_descr (DW_OP_push_object_address, 0, 0); + + switch (TREE_CODE (val)) + { + case NOP_EXPR: + case CONVERT_EXPR: + return descr_info_loc (TREE_OPERAND (val, 0), base_decl); + case INTEGER_CST: + if (host_integerp (val, 0)) + return int_loc_descriptor (tree_low_cst (val, 0)); + break; + case INDIRECT_REF: + size = int_size_in_bytes (TREE_TYPE (val)); + if (size < 0) + break; + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; + if (size == DWARF2_ADDR_SIZE) + add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0)); + else + add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0)); + return loc; + case POINTER_PLUS_EXPR: + case PLUS_EXPR: + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; + if (host_integerp (TREE_OPERAND (val, 1), 1) + && (unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (val, 1), 1) + < 16384) + add_loc_descr (&loc, + new_loc_descr (DW_OP_plus_uconst, + tree_low_cst (TREE_OPERAND (val, 1), + 1), 0)); + else + { + loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl); + if (!loc2) + break; + add_loc_descr (&loc, loc2); + add_loc_descr (&loc2, new_loc_descr (DW_OP_plus, 0, 0)); + } + return loc; + case MULT_EXPR: + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl); + if (!loc || !loc2) + break; + add_loc_descr (&loc, loc2); + add_loc_descr (&loc2, new_loc_descr (DW_OP_mul, 0, 0)); + return loc; + default: + break; + } + return NULL; +} + +static void +add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr, + tree val, tree base_decl) +{ + dw_loc_descr_ref loc; + + if (host_integerp (val, 0)) + { + add_AT_unsigned (die, attr, tree_low_cst (val, 0)); + return; + } + + loc = descr_info_loc (val, base_decl); + if (!loc) + return; + + add_AT_loc (die, attr, loc); +} + +/* This routine generates DIE for array with hidden descriptor, details + are filled into *info by a langhook. */ + +static void +gen_descr_array_type_die (tree type, struct array_descr_info *info, + dw_die_ref context_die) +{ + dw_die_ref scope_die = scope_die_for (type, context_die); + dw_die_ref array_die; + int dim; + + array_die = new_die (DW_TAG_array_type, scope_die, type); + add_name_attribute (array_die, type_tag (type)); + equate_type_number_to_die (type, array_die); + + if (info->associated) + add_descr_info_field (array_die, DW_AT_associated, info->associated, + info->base_decl); + if (info->allocated) + add_descr_info_field (array_die, DW_AT_allocated, info->allocated, + info->base_decl); + if (info->data_location) + add_descr_info_field (array_die, DW_AT_data_location, info->data_location, + info->base_decl); + + for (dim = 0; dim < info->ndimensions; dim++) + { + dw_die_ref subrange_die + = new_die (DW_TAG_subrange_type, array_die, NULL); + + if (info->dimen[dim].lower_bound) + { + /* If it is the default value, omit it. */ + if ((is_c_family () || is_java ()) + && integer_zerop (info->dimen[dim].lower_bound)) + ; + else if (is_fortran () + && integer_onep (info->dimen[dim].lower_bound)) + ; + else + add_descr_info_field (subrange_die, DW_AT_lower_bound, + info->dimen[dim].lower_bound, + info->base_decl); + } + if (info->dimen[dim].upper_bound) + add_descr_info_field (subrange_die, DW_AT_upper_bound, + info->dimen[dim].upper_bound, + info->base_decl); + if (info->dimen[dim].stride) + add_descr_info_field (subrange_die, DW_AT_byte_stride, + info->dimen[dim].stride, + info->base_decl); + } + + gen_type_die (info->element_type, context_die); + add_type_attribute (array_die, info->element_type, 0, 0, context_die); + + if (get_AT (array_die, DW_AT_name)) + add_pubtype (type, array_die); +} + #if 0 static void gen_entry_point_die (tree decl, dw_die_ref context_die) @@ -13071,6 +13217,7 @@ gen_type_die_with_usage (tree type, dw_d enum debug_info_usage usage) { int need_pop; + struct array_descr_info info; if (type == NULL_TREE || type == error_mark_node) return; @@ -13089,6 +13236,16 @@ gen_type_die_with_usage (tree type, dw_d return; } + /* If this is an array type with hidden descriptor, handle it first. */ + if (!TREE_ASM_WRITTEN (type) + && lang_hooks.types.get_array_descr_info + && lang_hooks.types.get_array_descr_info (type, &info)) + { + gen_descr_array_type_die (type, &info, context_die); + TREE_ASM_WRITTEN (type) = 1; + return; + } + /* We are going to output a DIE to represent the unqualified version of this type (i.e. without any const or volatile qualifiers) so get the main variant (i.e. the unqualified version) of this type --- gcc/dwarf2out.h.jj 2007-08-13 15:11:18.000000000 +0200 +++ gcc/dwarf2out.h 2007-11-09 17:47:55.000000000 +0100 @@ -25,3 +25,19 @@ extern void debug_dwarf (void); struct die_struct; extern void debug_dwarf_die (struct die_struct *); extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *)); + +struct array_descr_info +{ + int ndimensions; + tree element_type; + tree base_decl; + tree data_location; + tree allocated; + tree associated; + struct array_descr_dimen + { + tree lower_bound; + tree upper_bound; + tree stride; + } dimen[10]; +}; --- gcc/langhooks.h.jj 2007-11-02 19:02:47.000000000 +0100 +++ gcc/langhooks.h 2007-11-09 17:37:44.000000000 +0100 @@ -28,6 +28,8 @@ struct diagnostic_info; struct gimplify_omp_ctx; +struct array_descr_info; + /* A print hook for print_tree (). */ typedef void (*lang_print_tree_hook) (FILE *, tree, int indent); @@ -136,6 +138,10 @@ struct lang_hooks_for_types FUNCTION_TYPEs. */ bool (*type_hash_eq) (const_tree, const_tree); + /* Return TRUE if TYPE uses a hidden descriptor and fills in information + for the debugger about the array bounds, strides, etc. */ + bool (*get_array_descr_info) (const_tree, struct array_descr_info *); + /* Nonzero if types that are identical are to be hashed so that only one copy is kept. If a language requires unique types for each user-specified type, such as Ada, this should be set to TRUE. */ --- gcc/dwarf2.h.jj 2007-08-13 15:11:18.000000000 +0200 +++ gcc/dwarf2.h 2007-11-09 18:02:44.000000000 +0100 @@ -274,7 +274,8 @@ enum dwarf_attribute DW_AT_prototyped = 0x27, DW_AT_return_addr = 0x2a, DW_AT_start_scope = 0x2c, - DW_AT_stride_size = 0x2e, + DW_AT_bit_stride = 0x2e, + DW_AT_stride_size = DW_AT_bit_stride, DW_AT_upper_bound = 0x2f, DW_AT_abstract_origin = 0x31, DW_AT_accessibility = 0x32, @@ -309,7 +310,8 @@ enum dwarf_attribute DW_AT_allocated = 0x4e, DW_AT_associated = 0x4f, DW_AT_data_location = 0x50, - DW_AT_stride = 0x51, + DW_AT_byte_stride = 0x51, + DW_AT_stride = DW_AT_byte_stride, DW_AT_entry_pc = 0x52, DW_AT_use_UTF8 = 0x53, DW_AT_extension = 0x54, [-- Attachment #3: a4.f90 --] [-- Type: text/plain, Size: 1291 bytes --] subroutine baz real, allocatable :: varx (:, :, :) allocate (varx (1:6, 5:15, 17:28)) varx(:, :, :) = 6 varx(1, 5, 17) = 7 varx(2, 6, 18) = 8 varx(6, 15, 28) = 9 deallocate (varx) end subroutine baz subroutine foo (vary, varw) real :: vary (:, :) real :: varw (:, :, :) vary(:, :) = 4 vary(1, 1) = 8 vary(2, 2) = 9 vary(1, 3) = 10 varw(:, :, :) = 5 varw(1, 1, 1) = 6 varw(2, 2, 2) = 7 end subroutine foo subroutine bar (varz) real :: varz (*) varz(1:3) = 4 varz(2) = 5 end subroutine bar program test interface subroutine foo (vary, varw) real :: vary (:, :) real :: varw (:, :, :) end subroutine end interface interface subroutine bar (varz) real :: varz (*) end subroutine end interface real :: x (10, 10), y (5), z(8, 8, 8) x(:,:) = 1 y(:) = 2 z(:,:,:) = 3 call baz call foo (x, z(2:6, 4:7, 6:8)) call bar (y) if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort if (x (1, 3) .ne. 10) call abort if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort call foo (transpose (x), z) if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort if (x (3, 1) .ne. 10) call abort end [-- Attachment #4: a4.s.bz2 --] [-- Type: application/x-bzip2, Size: 6027 bytes --] ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-12 13:39 [RFC PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) Jakub Jelinek @ 2007-11-16 11:58 ` Jakub Jelinek 2007-11-16 13:24 ` Tobias Burnus 0 siblings, 1 reply; 11+ messages in thread From: Jakub Jelinek @ 2007-11-16 11:58 UTC (permalink / raw) To: gcc-patches, fortran; +Cc: Jan Kratochvil, Daniel Jacobowitz Hi! On Mon, Nov 12, 2007 at 05:46:03AM -0500, Jakub Jelinek wrote: > gfortran since my last patch at least emits useful debug info > for normal multi-dimensional arrays and arrays with lower bound different > than 0, including I believe assumed size arrays. > But it doesn't handle assumed shape arrays, allocatable and pointer arrays > that use descriptors. > For these DWARF3 has quite detailed example how can they be efficiently > described in D.2.1. The following patch tries to implement that. > I chose to use a langhook, because this would be terribly hard to express > in a generic way, we'd need new tree types for that and, as we want to > describe it using the DW_push_object_address magic, quite cumbersome. Here is the final version of the patch which fixes a bunch of errors in the debuginfo emitted by earlier patch, add supports for DW_AT_associated and DW_AT_allocated DWARF3 attributes and also adds support for assumed-size arrays. Jan Kratochvil posted a series of corresponding GDB patches in http://sources.redhat.com/ml/gdb-patches/2007-11/msg00317.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00315.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00316.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00318.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00319.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00320.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00322.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00321.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00326.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00323.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00324.html http://sources.redhat.com/ml/gdb-patches/2007-11/msg00325.html Bootstrapped/regtested on i686-linux and ppc64-linux (and x86_64-linux bootstrap is pending), ok for trunk? 2007-11-16 Jakub Jelinek <jakub@redhat.com> PR fortran/22244 * langhooks-def.h (LANG_HOOKS_GET_ARRAY_DESCR_INFO): Define. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add it. * langhooks.h (struct array_descr_info): Forward declaration. (struct lang_hooks_for_types): Add get_array_descr_info field. * dwarf2.h (DW_AT_bit_stride, DW_AT_byte_stride): New. (DW_AT_stride_size, DW_AT_stride): Keep around for Dwarf2 compatibility. * dwarf2out.h (struct array_descr_info): New type. * dwarf2out.c (dwarf_attr_name): Rename DW_AT_stride to DW_AT_byte_stride and DW_AT_stride_size to DW_AT_bit_size. (descr_info_loc, add_descr_info_field, gen_descr_array_type_die): New functions. (gen_type_die_with_usage): Call lang_hooks.types.get_array_descr_info and gen_descr_array_type_die. * trans.h (struct array_descr_info): Forward declaration. (gfc_get_array_descr_info): New prototype. (enum gfc_array_kind): New type. (struct lang_type): Add akind field. (GFC_TYPE_ARRAY_AKIND): Define. * trans-types.c: Include dwarf2out.h. (gfc_build_array_type): Add akind argument. Adjust gfc_get_array_type_bounds call. (gfc_get_nodesc_array_type): Include proper debug info even for assumed-size arrays. (gfc_get_array_type_bounds): Add akind argument, set GFC_TYPE_ARRAY_AKIND to it. (gfc_sym_type, gfc_get_derived_type): Adjust gfc_build_array_type callers. (gfc_get_array_descr_info): New function. * trans-array.c (gfc_trans_create_temp_array, gfc_conv_expr_descriptor): Adjust gfc_get_array_type_bounds callers. * trans-stmt.c (gfc_trans_pointer_assign_need_temp): Likewise. * trans-types.h (gfc_get_array_type_bounds): Adjust prototype. * Make-lang.in (fortran/trans-types.o): Depend on dwarf2out.h. * f95-lang.c (LANG_HOOKS_GET_ARRAY_DESCR_INFO): Define. --- gcc/fortran/trans.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/trans.h 2007-11-13 17:10:08.000000000 +0100 @@ -483,6 +483,8 @@ tree poplevel (int, int, int); tree getdecls (void); tree gfc_truthvalue_conversion (tree); tree gfc_builtin_function (tree); +struct array_descr_info; +bool gfc_get_array_descr_info (const_tree, struct array_descr_info *); /* In trans-openmp.c */ bool gfc_omp_privatize_by_reference (const_tree); @@ -569,10 +571,19 @@ extern GTY(()) tree gfor_fndecl_sr_kind; /* G95-specific declaration information. */ +enum gfc_array_kind +{ + GFC_ARRAY_UNKNOWN, + GFC_ARRAY_ASSUMED_SHAPE, + GFC_ARRAY_ALLOCATABLE, + GFC_ARRAY_POINTER +}; + /* Array types only. */ struct lang_type GTY(()) { int rank; + enum gfc_array_kind akind; tree lbound[GFC_MAX_DIMENSIONS]; tree ubound[GFC_MAX_DIMENSIONS]; tree stride[GFC_MAX_DIMENSIONS]; @@ -626,7 +637,8 @@ struct lang_decl GTY(()) #define GFC_TYPE_ARRAY_RANK(node) (TYPE_LANG_SPECIFIC(node)->rank) #define GFC_TYPE_ARRAY_SIZE(node) (TYPE_LANG_SPECIFIC(node)->size) #define GFC_TYPE_ARRAY_OFFSET(node) (TYPE_LANG_SPECIFIC(node)->offset) -/* Code should use gfc_get_dtype instead of accesig this directly. It may +#define GFC_TYPE_ARRAY_AKIND(node) (TYPE_LANG_SPECIFIC(node)->akind) +/* Code should use gfc_get_dtype instead of accesing this directly. It may not be known when the type is created. */ #define GFC_TYPE_ARRAY_DTYPE(node) (TYPE_LANG_SPECIFIC(node)->dtype) #define GFC_TYPE_ARRAY_DATAPTR_TYPE(node) \ --- gcc/fortran/trans-stmt.c.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/trans-stmt.c 2007-11-13 17:10:08.000000000 +0100 @@ -2525,7 +2525,8 @@ gfc_trans_pointer_assign_need_temp (gfc_ /* Make a new descriptor. */ parmtype = gfc_get_element_type (TREE_TYPE (desc)); parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, - loop.from, loop.to, 1); + loop.from, loop.to, 1, + GFC_ARRAY_UNKNOWN); /* Allocate temporary for nested forall construct. */ tmp1 = allocate_temp_for_forall_nest (nested_forall_info, parmtype, --- gcc/fortran/f95-lang.c.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/f95-lang.c 2007-11-13 17:10:08.000000000 +0100 @@ -120,6 +120,7 @@ static alias_set_type gfc_get_alias_set #undef LANG_HOOKS_OMP_PRIVATE_DEBUG_CLAUSE #undef LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES #undef LANG_HOOKS_BUILTIN_FUNCTION +#undef LANG_HOOKS_GET_ARRAY_DESCR_INFO /* Define lang hooks. */ #define LANG_HOOKS_NAME "GNU F95" @@ -143,6 +144,7 @@ static alias_set_type gfc_get_alias_set #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \ gfc_omp_firstprivatize_type_sizes #define LANG_HOOKS_BUILTIN_FUNCTION gfc_builtin_function +#define LANG_HOOKS_GET_ARRAY_DESCR_INFO gfc_get_array_descr_info const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; --- gcc/fortran/Make-lang.in.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/Make-lang.in 2007-11-13 17:10:08.000000000 +0100 @@ -312,7 +312,7 @@ fortran/trans-decl.o: $(GFORTRAN_TRANS_D $(CGRAPH_H) $(TARGET_H) $(FUNCTION_H) $(FLAGS_H) $(RTL_H) $(TREE_GIMPLE_H) \ $(TREE_DUMP_H) fortran/trans-types.o: $(GFORTRAN_TRANS_DEPS) gt-fortran-trans-types.h \ - $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) + $(REAL_H) toplev.h $(TARGET_H) $(FLAGS_H) dwarf2out.h fortran/trans-const.o: $(GFORTRAN_TRANS_DEPS) fortran/trans-expr.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h fortran/trans-stmt.o: $(GFORTRAN_TRANS_DEPS) fortran/dependency.h --- gcc/fortran/trans-types.c.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/trans-types.c 2007-11-14 15:24:57.000000000 +0100 @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. #include "trans-const.h" #include "real.h" #include "flags.h" +#include "dwarf2out.h" \f #if (GFC_MAX_DIMENSIONS < 10) @@ -1047,7 +1048,8 @@ gfc_is_nodesc_array (gfc_symbol * sym) /* Create an array descriptor type. */ static tree -gfc_build_array_type (tree type, gfc_array_spec * as) +gfc_build_array_type (tree type, gfc_array_spec * as, + enum gfc_array_kind akind) { tree lbound[GFC_MAX_DIMENSIONS]; tree ubound[GFC_MAX_DIMENSIONS]; @@ -1063,7 +1065,9 @@ gfc_build_array_type (tree type, gfc_arr ubound[n] = gfc_conv_array_bound (as->upper[n]); } - return gfc_get_array_type_bounds (type, as->rank, lbound, ubound, 0); + if (as->type == AS_ASSUMED_SHAPE) + akind = GFC_ARRAY_ASSUMED_SHAPE; + return gfc_get_array_type_bounds (type, as->rank, lbound, ubound, 0, akind); } \f /* Returns the struct descriptor_dimension type. */ @@ -1246,7 +1250,7 @@ gfc_get_nodesc_array_type (tree etype, g if (expr->expr_type == EXPR_CONSTANT) { tmp = gfc_conv_mpz_to_tree (expr->value.integer, - gfc_index_integer_kind); + gfc_index_integer_kind); } else { @@ -1338,7 +1342,7 @@ gfc_get_nodesc_array_type (tree etype, g /* In debug info represent packed arrays as multi-dimensional if they have rank > 1 and with proper bounds, instead of flat arrays. */ - if (known_stride && write_symbols != NO_DEBUG) + if (known_offset && write_symbols != NO_DEBUG) { tree gtype = etype, rtype, type_decl; @@ -1428,7 +1432,8 @@ gfc_get_array_descriptor_base (int dimen tree gfc_get_array_type_bounds (tree etype, int dimen, tree * lbound, - tree * ubound, int packed) + tree * ubound, int packed, + enum gfc_array_kind akind) { char name[8 + GFC_RANK_DIGITS + GFC_MAX_SYMBOL_LEN]; tree fat_type, base_type, arraytype, lower, upper, stride, tmp; @@ -1455,6 +1460,7 @@ gfc_get_array_type_bounds (tree etype, i GFC_TYPE_ARRAY_RANK (fat_type) = dimen; GFC_TYPE_ARRAY_DTYPE (fat_type) = NULL_TREE; + GFC_TYPE_ARRAY_AKIND (fat_type) = akind; /* Build an array descriptor record type. */ if (packed != 0) @@ -1573,9 +1579,14 @@ gfc_sym_type (gfc_symbol * sym) } } else - { - type = gfc_build_array_type (type, sym->as); - } + { + enum gfc_array_kind akind = GFC_ARRAY_UNKNOWN; + if (sym->attr.pointer) + akind = GFC_ARRAY_POINTER; + else if (sym->attr.allocatable) + akind = GFC_ARRAY_ALLOCATABLE; + type = gfc_build_array_type (type, sym->as, akind); + } } else { @@ -1801,9 +1812,14 @@ gfc_get_derived_type (gfc_symbol * deriv { if (c->pointer || c->allocatable) { + enum gfc_array_kind akind; + if (c->pointer) + akind = GFC_ARRAY_POINTER; + else + akind = GFC_ARRAY_ALLOCATABLE; /* Pointers to arrays aren't actually pointer types. The descriptors are separate, but the data is common. */ - field_type = gfc_build_array_type (field_type, c->as); + field_type = gfc_build_array_type (field_type, c->as, akind); } else field_type = gfc_get_nodesc_array_type (field_type, c->as, @@ -2121,4 +2137,124 @@ gfc_type_for_mode (enum machine_mode mod return NULL_TREE; } +/* Return TRUE if TYPE is a type with a hidden descriptor, fill in INFO + in that case. */ + +bool +gfc_get_array_descr_info (const_tree type, struct array_descr_info *info) +{ + int rank, dim; + bool indirect = false; + tree etype, ptype, field, t, base_decl; + tree data_off, offset_off, dim_off, dim_size, elem_size; + tree lower_suboff, upper_suboff, stride_suboff; + + if (! GFC_DESCRIPTOR_TYPE_P (type)) + { + if (! POINTER_TYPE_P (type)) + return false; + type = TREE_TYPE (type); + if (! GFC_DESCRIPTOR_TYPE_P (type)) + return false; + indirect = true; + } + + rank = GFC_TYPE_ARRAY_RANK (type); + if (rank >= (int) (sizeof (info->dimen) / sizeof (info->dimen[0]))) + return false; + + etype = GFC_TYPE_ARRAY_DATAPTR_TYPE (type); + gcc_assert (POINTER_TYPE_P (etype)); + etype = TREE_TYPE (etype); + gcc_assert (TREE_CODE (etype) == ARRAY_TYPE); + etype = TREE_TYPE (etype); + /* Can't handle variable sized elements yet. */ + if (int_size_in_bytes (etype) <= 0) + return false; + /* Nor non-constant lower bounds in assumed shape arrays. */ + if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE) + { + for (dim = 0; dim < rank; dim++) + if (GFC_TYPE_ARRAY_LBOUND (type, dim) == NULL_TREE + || TREE_CODE (GFC_TYPE_ARRAY_LBOUND (type, dim)) != INTEGER_CST) + return false; + } + + memset (info, '\0', sizeof (*info)); + info->ndimensions = rank; + info->element_type = etype; + ptype = build_pointer_type (gfc_array_index_type); + if (indirect) + { + info->base_decl = build_decl (VAR_DECL, NULL_TREE, + build_pointer_type (ptype)); + base_decl = build1 (INDIRECT_REF, ptype, info->base_decl); + } + else + info->base_decl = base_decl = build_decl (VAR_DECL, NULL_TREE, ptype); + + elem_size = fold_convert (gfc_array_index_type, TYPE_SIZE_UNIT (etype)); + field = TYPE_FIELDS (TYPE_MAIN_VARIANT (type)); + data_off = byte_position (field); + field = TREE_CHAIN (field); + offset_off = byte_position (field); + field = TREE_CHAIN (field); + field = TREE_CHAIN (field); + dim_off = byte_position (field); + dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field))); + field = TYPE_FIELDS (TREE_TYPE (TREE_TYPE (field))); + stride_suboff = byte_position (field); + field = TREE_CHAIN (field); + lower_suboff = byte_position (field); + field = TREE_CHAIN (field); + upper_suboff = byte_position (field); + + t = base_decl; + if (!integer_zerop (data_off)) + t = build2 (POINTER_PLUS_EXPR, ptype, t, data_off); + t = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), t); + info->data_location = build1 (INDIRECT_REF, ptr_type_node, t); + if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE) + info->allocated = build2 (NE_EXPR, boolean_type_node, + info->data_location, null_pointer_node); + else if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER) + info->associated = build2 (NE_EXPR, boolean_type_node, + info->data_location, null_pointer_node); + + for (dim = 0; dim < rank; dim++) + { + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, lower_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + info->dimen[dim].lower_bound = t; + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, upper_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + info->dimen[dim].upper_bound = t; + if (GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_SHAPE) + { + /* Assumed shape arrays have known lower bounds. */ + info->dimen[dim].upper_bound + = build2 (MINUS_EXPR, gfc_array_index_type, + info->dimen[dim].upper_bound, + info->dimen[dim].lower_bound); + info->dimen[dim].lower_bound + = fold_convert (gfc_array_index_type, + GFC_TYPE_ARRAY_LBOUND (type, dim)); + info->dimen[dim].upper_bound + = build2 (PLUS_EXPR, gfc_array_index_type, + info->dimen[dim].lower_bound, + info->dimen[dim].upper_bound); + } + t = build2 (POINTER_PLUS_EXPR, ptype, base_decl, + size_binop (PLUS_EXPR, dim_off, stride_suboff)); + t = build1 (INDIRECT_REF, gfc_array_index_type, t); + t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size); + info->dimen[dim].stride = t; + dim_off = size_binop (PLUS_EXPR, dim_off, dim_size); + } + + return true; +} + #include "gt-fortran-trans-types.h" --- gcc/fortran/trans-array.c.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/trans-array.c 2007-11-13 17:10:08.000000000 +0100 @@ -608,7 +608,8 @@ gfc_trans_create_temp_array (stmtblock_t /* Initialize the descriptor. */ type = - gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1); + gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1, + GFC_ARRAY_UNKNOWN); desc = gfc_create_var (type, "atmp"); GFC_DECL_PACKED_ARRAY (desc) = 1; @@ -4788,7 +4789,8 @@ gfc_conv_expr_descriptor (gfc_se * se, g /* Otherwise make a new one. */ parmtype = gfc_get_element_type (TREE_TYPE (desc)); parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, - loop.from, loop.to, 0); + loop.from, loop.to, 0, + GFC_ARRAY_UNKNOWN); parm = gfc_create_var (parmtype, "parm"); } --- gcc/fortran/trans-types.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/fortran/trans-types.h 2007-11-13 17:10:08.000000000 +0100 @@ -67,7 +67,8 @@ tree gfc_type_for_size (unsigned, int); tree gfc_type_for_mode (enum machine_mode, int); tree gfc_get_element_type (tree); -tree gfc_get_array_type_bounds (tree, int, tree *, tree *, int); +tree gfc_get_array_type_bounds (tree, int, tree *, tree *, int, + enum gfc_array_kind); tree gfc_get_nodesc_array_type (tree, gfc_array_spec *, gfc_packed); /* Add a field of given name and type to a UNION_TYPE or RECORD_TYPE. */ --- gcc/dwarf2.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/dwarf2.h 2007-11-13 17:10:08.000000000 +0100 @@ -274,7 +274,8 @@ enum dwarf_attribute DW_AT_prototyped = 0x27, DW_AT_return_addr = 0x2a, DW_AT_start_scope = 0x2c, - DW_AT_stride_size = 0x2e, + DW_AT_bit_stride = 0x2e, + DW_AT_stride_size = DW_AT_bit_stride, DW_AT_upper_bound = 0x2f, DW_AT_abstract_origin = 0x31, DW_AT_accessibility = 0x32, @@ -309,7 +310,8 @@ enum dwarf_attribute DW_AT_allocated = 0x4e, DW_AT_associated = 0x4f, DW_AT_data_location = 0x50, - DW_AT_stride = 0x51, + DW_AT_byte_stride = 0x51, + DW_AT_stride = DW_AT_byte_stride, DW_AT_entry_pc = 0x52, DW_AT_use_UTF8 = 0x53, DW_AT_extension = 0x54, --- gcc/langhooks.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/langhooks.h 2007-11-13 17:10:08.000000000 +0100 @@ -28,6 +28,8 @@ struct diagnostic_info; struct gimplify_omp_ctx; +struct array_descr_info; + /* A print hook for print_tree (). */ typedef void (*lang_print_tree_hook) (FILE *, tree, int indent); @@ -136,6 +138,10 @@ struct lang_hooks_for_types FUNCTION_TYPEs. */ bool (*type_hash_eq) (const_tree, const_tree); + /* Return TRUE if TYPE uses a hidden descriptor and fills in information + for the debugger about the array bounds, strides, etc. */ + bool (*get_array_descr_info) (const_tree, struct array_descr_info *); + /* Nonzero if types that are identical are to be hashed so that only one copy is kept. If a language requires unique types for each user-specified type, such as Ada, this should be set to TRUE. */ --- gcc/langhooks-def.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/langhooks-def.h 2007-11-13 17:10:08.000000000 +0100 @@ -180,6 +180,7 @@ extern tree lhd_make_node (enum tree_cod #define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \ lhd_omp_firstprivatize_type_sizes #define LANG_HOOKS_TYPE_HASH_EQ NULL +#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL #define LANG_HOOKS_HASH_TYPES true #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \ @@ -193,6 +194,7 @@ extern tree lhd_make_node (enum tree_cod LANG_HOOKS_TYPE_MAX_SIZE, \ LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \ LANG_HOOKS_TYPE_HASH_EQ, \ + LANG_HOOKS_GET_ARRAY_DESCR_INFO, \ LANG_HOOKS_HASH_TYPES \ } --- gcc/dwarf2out.c.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/dwarf2out.c 2007-11-13 17:10:08.000000000 +0100 @@ -4263,6 +4263,7 @@ static tree member_declared_type (const_ static const char *decl_start_label (tree); #endif static void gen_array_type_die (tree, dw_die_ref); +static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_ref); #if 0 static void gen_entry_point_die (tree, dw_die_ref); #endif @@ -4669,8 +4670,8 @@ dwarf_attr_name (unsigned int attr) return "DW_AT_return_addr"; case DW_AT_start_scope: return "DW_AT_start_scope"; - case DW_AT_stride_size: - return "DW_AT_stride_size"; + case DW_AT_bit_stride: + return "DW_AT_bit_stride"; case DW_AT_upper_bound: return "DW_AT_upper_bound"; case DW_AT_abstract_origin: @@ -4738,8 +4739,8 @@ dwarf_attr_name (unsigned int attr) return "DW_AT_associated"; case DW_AT_data_location: return "DW_AT_data_location"; - case DW_AT_stride: - return "DW_AT_stride"; + case DW_AT_byte_stride: + return "DW_AT_byte_stride"; case DW_AT_entry_pc: return "DW_AT_entry_pc"; case DW_AT_use_UTF8: @@ -11675,6 +11676,163 @@ gen_array_type_die (tree type, dw_die_re add_pubtype (type, array_die); } +static dw_loc_descr_ref +descr_info_loc (tree val, tree base_decl) +{ + HOST_WIDE_INT size; + dw_loc_descr_ref loc, loc2; + enum dwarf_location_atom op; + + if (val == base_decl) + return new_loc_descr (DW_OP_push_object_address, 0, 0); + + switch (TREE_CODE (val)) + { + case NOP_EXPR: + case CONVERT_EXPR: + return descr_info_loc (TREE_OPERAND (val, 0), base_decl); + case INTEGER_CST: + if (host_integerp (val, 0)) + return int_loc_descriptor (tree_low_cst (val, 0)); + break; + case INDIRECT_REF: + size = int_size_in_bytes (TREE_TYPE (val)); + if (size < 0) + break; + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; + if (size == DWARF2_ADDR_SIZE) + add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0)); + else + add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0)); + return loc; + case POINTER_PLUS_EXPR: + case PLUS_EXPR: + if (host_integerp (TREE_OPERAND (val, 1), 1) + && (unsigned HOST_WIDE_INT) tree_low_cst (TREE_OPERAND (val, 1), 1) + < 16384) + { + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; + add_loc_descr (&loc, + new_loc_descr (DW_OP_plus_uconst, + tree_low_cst (TREE_OPERAND (val, 1), + 1), 0)); + } + else + { + op = DW_OP_plus; + do_binop: + loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl); + if (!loc) + break; + loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl); + if (!loc2) + break; + add_loc_descr (&loc, loc2); + add_loc_descr (&loc2, new_loc_descr (op, 0, 0)); + } + return loc; + case MINUS_EXPR: + op = DW_OP_minus; + goto do_binop; + case MULT_EXPR: + op = DW_OP_mul; + goto do_binop; + case EQ_EXPR: + op = DW_OP_eq; + goto do_binop; + case NE_EXPR: + op = DW_OP_ne; + goto do_binop; + default: + break; + } + return NULL; +} + +static void +add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr, + tree val, tree base_decl) +{ + dw_loc_descr_ref loc; + + if (host_integerp (val, 0)) + { + add_AT_unsigned (die, attr, tree_low_cst (val, 0)); + return; + } + + loc = descr_info_loc (val, base_decl); + if (!loc) + return; + + add_AT_loc (die, attr, loc); +} + +/* This routine generates DIE for array with hidden descriptor, details + are filled into *info by a langhook. */ + +static void +gen_descr_array_type_die (tree type, struct array_descr_info *info, + dw_die_ref context_die) +{ + dw_die_ref scope_die = scope_die_for (type, context_die); + dw_die_ref array_die; + int dim; + + array_die = new_die (DW_TAG_array_type, scope_die, type); + add_name_attribute (array_die, type_tag (type)); + equate_type_number_to_die (type, array_die); + + if (info->data_location) + add_descr_info_field (array_die, DW_AT_data_location, info->data_location, + info->base_decl); + if (info->associated) + add_descr_info_field (array_die, DW_AT_associated, info->associated, + info->base_decl); + if (info->allocated) + add_descr_info_field (array_die, DW_AT_allocated, info->allocated, + info->base_decl); + + for (dim = 0; dim < info->ndimensions; dim++) + { + dw_die_ref subrange_die + = new_die (DW_TAG_subrange_type, array_die, NULL); + + if (info->dimen[dim].lower_bound) + { + /* If it is the default value, omit it. */ + if ((is_c_family () || is_java ()) + && integer_zerop (info->dimen[dim].lower_bound)) + ; + else if (is_fortran () + && integer_onep (info->dimen[dim].lower_bound)) + ; + else + add_descr_info_field (subrange_die, DW_AT_lower_bound, + info->dimen[dim].lower_bound, + info->base_decl); + } + if (info->dimen[dim].upper_bound) + add_descr_info_field (subrange_die, DW_AT_upper_bound, + info->dimen[dim].upper_bound, + info->base_decl); + if (info->dimen[dim].stride) + add_descr_info_field (subrange_die, DW_AT_byte_stride, + info->dimen[dim].stride, + info->base_decl); + } + + gen_type_die (info->element_type, context_die); + add_type_attribute (array_die, info->element_type, 0, 0, context_die); + + if (get_AT (array_die, DW_AT_name)) + add_pubtype (type, array_die); +} + #if 0 static void gen_entry_point_die (tree decl, dw_die_ref context_die) @@ -13051,6 +13209,7 @@ gen_type_die_with_usage (tree type, dw_d enum debug_info_usage usage) { int need_pop; + struct array_descr_info info; if (type == NULL_TREE || type == error_mark_node) return; @@ -13069,6 +13228,16 @@ gen_type_die_with_usage (tree type, dw_d return; } + /* If this is an array type with hidden descriptor, handle it first. */ + if (!TREE_ASM_WRITTEN (type) + && lang_hooks.types.get_array_descr_info + && lang_hooks.types.get_array_descr_info (type, &info)) + { + gen_descr_array_type_die (type, &info, context_die); + TREE_ASM_WRITTEN (type) = 1; + return; + } + /* We are going to output a DIE to represent the unqualified version of this type (i.e. without any const or volatile qualifiers) so get the main variant (i.e. the unqualified version) of this type --- gcc/dwarf2out.h.jj 2007-11-13 17:06:40.000000000 +0100 +++ gcc/dwarf2out.h 2007-11-13 17:10:08.000000000 +0100 @@ -25,3 +25,19 @@ extern void debug_dwarf (void); struct die_struct; extern void debug_dwarf_die (struct die_struct *); extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *)); + +struct array_descr_info +{ + int ndimensions; + tree element_type; + tree base_decl; + tree data_location; + tree allocated; + tree associated; + struct array_descr_dimen + { + tree lower_bound; + tree upper_bound; + tree stride; + } dimen[10]; +}; Jakub ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 11:58 ` [PATCH] " Jakub Jelinek @ 2007-11-16 13:24 ` Tobias Burnus 2007-11-16 13:28 ` Jakub Jelinek 0 siblings, 1 reply; 11+ messages in thread From: Tobias Burnus @ 2007-11-16 13:24 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, fortran, Jan Kratochvil, Daniel Jacobowitz Hi Jakub, Jakub Jelinek wrote: > Here is the final version of the patch which fixes a bunch of errors in the > debuginfo emitted by earlier patch, add supports for DW_AT_associated and > DW_AT_allocated DWARF3 attributes and also adds support for assumed-size > arrays. > I applied the GCC patch and tried the example with the Intel Debugger 10. Tested was "a4.f90" of http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00612.html. Using ifort10, I get in "baz": (idb) ptype varx type = REAL(4)(6)(11)(12) (idb) p varx $1 = {{{7, 6, 6, 6, 6, 6}, {6 ... And using the patched gfortran: (idb) ptype varx type = REAL(4)(12)(11)(6) (idb) p varx $1 = {{{<no value>, <no value>, <no value>, I don't know whether this is a deficit in idb or in gcc/gfortran. Note: Not only does idb show "no value", it has also problems with the array extent. Accoding to http://sources.redhat.com/ml/gdb-patches/2007-11/msg00317.html the output of patched gcc + patched gdb is: (gdb) ptype varx type = real*4 (6,5:15,17:28) (gdb) p varx $1 = (( ( 7, 6, 6, 6, 6, 6) ( 6, 6, 6, 6, 6, 6) ( 6, [cut ...] which is ok. > Bootstrapped/regtested on i686-linux and ppc64-linux (and x86_64-linux > bootstrap is pending), ok for trunk? > The Fortran part looks OK. Tobias ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 13:24 ` Tobias Burnus @ 2007-11-16 13:28 ` Jakub Jelinek 2007-11-16 14:01 ` Tobias Burnus 0 siblings, 1 reply; 11+ messages in thread From: Jakub Jelinek @ 2007-11-16 13:28 UTC (permalink / raw) To: Tobias Burnus; +Cc: gcc-patches, fortran [-- Attachment #1: Type: text/plain, Size: 1041 bytes --] On Fri, Nov 16, 2007 at 12:45:02PM +0100, Tobias Burnus wrote: > I applied the GCC patch and tried the example with the Intel Debugger > 10. Tested was "a4.f90" of > http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00612.html. > > Using ifort10, I get in "baz": > > (idb) ptype varx > type = REAL(4)(6)(11)(12) > (idb) p varx > $1 = {{{7, 6, 6, 6, 6, 6}, {6 ... There is DW_AT_ordering attribute with { DW_ORD_col_major, DW_ORD_row_major } possible values. The standard says the default (if DW_AT_ordering is missing) depends on the language, but I couldn't find the default values for each language anywhere. GCC outputs arrays in the same order for all languages and GDB seems to default to DW_ORD_row_major if DW_AT_ordering is not present. Can you look at with idb on gfortran (vanilla or patched) generated MAIN__ x and y arrays after the bar subroutine returns and see if they are displayed in the expected order or not? Perhaps we should for all fortran multidimensional arrays output DW_AT_ordering with DW_ORD_row_major? Jakub [-- Attachment #2: a5.f90 --] [-- Type: text/plain, Size: 1890 bytes --] subroutine baz real, target, allocatable :: varx (:, :, :) real, pointer :: varv (:, :, :) real, target :: varu (1, 2, 3) logical :: l allocate (varx (1:6, 5:15, 17:28)) l = allocated (varx) varx(:, :, :) = 6 varx(1, 5, 17) = 7 varx(2, 6, 18) = 8 varx(6, 15, 28) = 9 varv => varx l = associated (varv) varv(3, 7, 19) = 10 varv => null () l = associated (varv) deallocate (varx) l = allocated (varx) varu(:, :, :) = 10 allocate (varv (1:6, 5:15, 17:28)) l = associated (varv) varv(:, :, :) = 6 varv(1, 5, 17) = 7 varv(2, 6, 18) = 8 varv(6, 15, 28) = 9 deallocate (varv) l = associated (varv) varv => varu varv(1, 1, 1) = 6 varv(1, 2, 3) = 7 l = associated (varv) end subroutine baz subroutine foo (vary, varw) real :: vary (:, :) real :: varw (:, :, :) vary(:, :) = 4 vary(1, 1) = 8 vary(2, 2) = 9 vary(1, 3) = 10 varw(:, :, :) = 5 varw(1, 1, 1) = 6 varw(2, 2, 2) = 7 end subroutine foo subroutine bar (varz, vart) real :: varz (*) real :: vart (2:11, 7:*) varz(1:3) = 4 varz(2) = 5 end subroutine bar program test interface subroutine foo (vary, varw) real :: vary (:, :) real :: varw (:, :, :) end subroutine end interface interface subroutine bar (varz, vart) real :: varz (*) real :: vart (2:11, 7:*) end subroutine end interface real :: x (10, 10), y (5), z(8, 8, 8) x(:,:) = 1 y(:) = 2 z(:,:,:) = 3 call baz call foo (x, z(2:6, 4:7, 6:8)) call bar (y, x) if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort if (x (1, 3) .ne. 10) call abort if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort call foo (transpose (x), z) if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort if (x (3, 1) .ne. 10) call abort end ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 13:28 ` Jakub Jelinek @ 2007-11-16 14:01 ` Tobias Burnus 2007-11-16 16:14 ` Jakub Jelinek 0 siblings, 1 reply; 11+ messages in thread From: Tobias Burnus @ 2007-11-16 14:01 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, fortran Jakub Jelinek wrote: > Can you look at with idb on gfortran (vanilla or patched) generated MAIN__ > x and y arrays after the bar subroutine returns and see if they are > displayed in the expected order or not? > For the a5.f90 test case, compiled with ifort (!) I get: Breakpoint 1, test () at a5.f90:70 70 if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort (idb) p x $1 = {{<no value>, <no value>, ... (idb) p y $2 = <no value> (idb) ptype x type = REAL(4)(10)(10) (idb) ptype y type = REAL(4)(5) while using gdb and ifort (!): (gdb) p x $1 = (( 8, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 9, 4, ... (gdb) p y $2 = (4, 5, 4, 2, 2) (gdb) ptype y type = real*4 (5) (gdb) ptype x type = real*4 (10,10) But now to your question, using (an unpatched) gfortran -g and idb: (idb) p x $1 = {{8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {9, 4, 4, 4, 4, 4, 4, 4, 4, 10, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}, {4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8.11898326e-11}} (idb) p y $2 = {4, 5, 4, 2, 2, 0} (idb) ptype x type = REAL(4)(11)(11) (idb) ptype y type = REAL(4)(6) While with the same binary and gdb: (gdb) p x $1 = (( 8, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 9, 4, 4, 4, 4, 4, 4, 4, 4) ( 10, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ( 4, 4, 4, 4, 4, 4, 4, 4, 4, 4) ) (gdb) p y $2 = (4, 5, 4, 2, 2) (gdb) ptype x type = real*4 (10,10) (gdb) ptype y type = real*4 (5) Tobias (PS: The gdb is w/o the patches.) ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 14:01 ` Tobias Burnus @ 2007-11-16 16:14 ` Jakub Jelinek 2007-11-16 18:09 ` Tobias Burnus 2007-12-09 15:13 ` Richard Guenther 0 siblings, 2 replies; 11+ messages in thread From: Jakub Jelinek @ 2007-11-16 16:14 UTC (permalink / raw) To: Tobias Burnus; +Cc: gcc-patches, fortran, jan.kratochvil On Fri, Nov 16, 2007 at 02:06:42PM +0100, Tobias Burnus wrote: > Jakub Jelinek wrote: > > Can you look at with idb on gfortran (vanilla or patched) generated MAIN__ > > x and y arrays after the bar subroutine returns and see if they are > > displayed in the expected order or not? > > > For the a5.f90 test case, compiled with ifort (!) I get: Ok, can you retry with the following additional patch on top of the previous one? It seems ifort emits DW_AT_subrange_type's in the same order as GCC, i.e. for (1:5, 4:7, 8:9) there is DW_AT_subrange_type DW_AT_lower_bound 1 DW_AT_upper_bound 5 DW_AT_subrange_type DW_AT_lower_bound 4 DW_AT_upper_bound 7 DW_AT_subrange_type DW_AT_lower_bound 8 DW_AT_upper_bound 9 but GCC doesn't add any DW_AT_ordering, while ifort adds DW_AT_ordering DW_ORD_col_major. Wonder what gdb will do in presence of DW_ORD_col_major, I fear that DW_ORD_col_major means it just reverses the order of DW_AT_subrange_type notes and has hardcoded another reordering for Fortran or something, Jan? --- gcc/dwarf2out.c.jj 2007-11-15 20:05:54.000000000 +0100 +++ gcc/dwarf2out.c 2007-11-16 14:16:13.000000000 +0100 @@ -11636,6 +11636,12 @@ gen_array_type_die (tree type, dw_die_re add_AT_flag (array_die, DW_AT_GNU_vector, 1); } + /* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */ + if (is_fortran () + && TREE_CODE (type) == ARRAY_TYPE + && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE) + add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major); + #if 0 /* We default the array ordering. SDB will probably do the right things even if DW_AT_ordering is not present. It's not even @@ -11787,6 +11793,11 @@ gen_descr_array_type_die (tree type, str add_name_attribute (array_die, type_tag (type)); equate_type_number_to_die (type, array_die); + /* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */ + if (is_fortran () + && info->ndimensions >= 2) + add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major); + if (info->data_location) add_descr_info_field (array_die, DW_AT_data_location, info->data_location, info->base_decl); Jakub ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 16:14 ` Jakub Jelinek @ 2007-11-16 18:09 ` Tobias Burnus 2007-11-16 19:05 ` Tobias Burnus 2007-11-16 19:05 ` Jakub Jelinek 2007-12-09 15:13 ` Richard Guenther 1 sibling, 2 replies; 11+ messages in thread From: Tobias Burnus @ 2007-11-16 18:09 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, fortran, jan.kratochvil Jakub Jelinek wrote: > On Fri, Nov 16, 2007 at 02:06:42PM +0100, Tobias Burnus wrote: > >> Jakub Jelinek wrote: >> >>> Can you look at with idb on gfortran (vanilla or patched) generated MAIN__ >>> x and y arrays after the bar subroutine returns and see if they are >>> displayed in the expected order or not? >>> >> For the a5.f90 test case, compiled with ifort (!) I get: >> > Ok, can you retry with the following additional patch on top of the previous > one? Now I get with gfortran (both patches) and idb (using a4.f90): (idb) ptype varx type = REAL(4)(6)(11)(12) Which looks ok. The problem with the <no value> seems to be that the deallocate comes too early - or that I cannot operate the debugger: (idb) next 6 varx(2, 6, 18) = 8 (idb) p varx $6 = {{{7, 6, 6, 6, 6, 6}, {6 (idb) next 7 varx(6, 15, 28) = 9 (idb) p varx $8 = {{{7, 6, 6, 6, 6, 6}, {6 (idb) next 8 deallocate (varx) (idb) p varx $9 = {{{<no value>, <no value>, * * * Regarding the test case a4.f90 and a4.f90: I get for x(3,1) with gfortran a "10.0" but with g95, nag f95 and ifort a "4.0", which indicates a bug in gfortran. Tobias ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 18:09 ` Tobias Burnus @ 2007-11-16 19:05 ` Tobias Burnus 2007-11-16 19:18 ` Jakub Jelinek 2007-11-16 19:05 ` Jakub Jelinek 1 sibling, 1 reply; 11+ messages in thread From: Tobias Burnus @ 2007-11-16 19:05 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches, fortran, jan.kratochvil Tobias Burnus wrote: > Regarding the test case a4.f90 and a4.f90: I get for x(3,1) with > gfortran a "10.0" but with g95, nag f95 and ifort a "4.0", which > indicates a bug in gfortran. > This is not a bug in gfortran but a bug in the program. A minimal test case is: program prog implicit none integer :: a(2,2) a = 0 call test(transpose(a)) print *, a contains subroutine test(x) ! intent(out) :: x ! uncommenting this gives a compile error integer :: x(:,:) x = 3 end subroutine test end program prog Here, the question is whether one can assign to "tranpose(a)" or not. gfortran does not create a copy of the variable "a" as the other compilers seem to do, but works with strides. Therefore, gfortran prints "3 3 3 3" and ifort, NAG f95, g95 and openf95 print "0 0 0 0". Turning on all debugging, NAG f95 prints at run time: Dummy argument X is associated with an expression - cannot assign And all compiler reject this example if one adds "INTENT(OUT)" for the dummy "x" in "test". Thus: If the example is for the test suite, please fix it. One way to do so is to change the subroutine into a function and returning the function. Or doing "x = tranpose(x)" before the call or ... Tobias ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 19:05 ` Tobias Burnus @ 2007-11-16 19:18 ` Jakub Jelinek 0 siblings, 0 replies; 11+ messages in thread From: Jakub Jelinek @ 2007-11-16 19:18 UTC (permalink / raw) To: Tobias Burnus; +Cc: gcc-patches, fortran, jan.kratochvil On Fri, Nov 16, 2007 at 05:36:53PM +0100, Tobias Burnus wrote: > Tobias Burnus wrote: > > Regarding the test case a4.f90 and a4.f90: I get for x(3,1) with > > gfortran a "10.0" but with g95, nag f95 and ifort a "4.0", which > > indicates a bug in gfortran. > > > > This is not a bug in gfortran but a bug in the program. A minimal test > case is: > > program prog > implicit none > integer :: a(2,2) > a = 0 > call test(transpose(a)) > print *, a > contains > subroutine test(x) > ! intent(out) :: x ! uncommenting this gives a compile error > integer :: x(:,:) > x = 3 > end subroutine test > end program prog Ok. The testcase was definitely meant to see the array with the swapped strides to see if the debugger can see it. If it can't assign it, it should just take another (say logical) argument and for the second case just read/compare the values rather than testing what ended up in the caller's array. The testcase isn't meant for gcc testsuite anyway. Or if you have better ideas how to get arrays with really weird stride setups, I think Jan will appreciate that for GDB testsuite. Jakub ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 18:09 ` Tobias Burnus 2007-11-16 19:05 ` Tobias Burnus @ 2007-11-16 19:05 ` Jakub Jelinek 1 sibling, 0 replies; 11+ messages in thread From: Jakub Jelinek @ 2007-11-16 19:05 UTC (permalink / raw) To: Tobias Burnus; +Cc: gcc-patches, fortran, jan.kratochvil On Fri, Nov 16, 2007 at 05:14:14PM +0100, Tobias Burnus wrote: > Regarding the test case a4.f90 and a4.f90: I get for x(3,1) with > gfortran a "10.0" but with g95, nag f95 and ifort a "4.0", which > indicates a bug in gfortran. That depends. There are two foo calls, one is called with x, one with transpose(x). So, x(3,1) is supposed to be 4.0 after the first foo and 10.0 after the second foo call. And it works just fine for me with gfortran. Jakub ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) 2007-11-16 16:14 ` Jakub Jelinek 2007-11-16 18:09 ` Tobias Burnus @ 2007-12-09 15:13 ` Richard Guenther 1 sibling, 0 replies; 11+ messages in thread From: Richard Guenther @ 2007-12-09 15:13 UTC (permalink / raw) To: Jakub Jelinek; +Cc: Tobias Burnus, gcc-patches, fortran, jan.kratochvil On Nov 16, 2007 2:28 PM, Jakub Jelinek <jakub@redhat.com> wrote: > On Fri, Nov 16, 2007 at 02:06:42PM +0100, Tobias Burnus wrote: > > Jakub Jelinek wrote: > > > Can you look at with idb on gfortran (vanilla or patched) generated MAIN__ > > > x and y arrays after the bar subroutine returns and see if they are > > > displayed in the expected order or not? > > > > > For the a5.f90 test case, compiled with ifort (!) I get: > > Ok, can you retry with the following additional patch on top of the previous > one? > It seems ifort emits DW_AT_subrange_type's in the same order as GCC, i.e. > for (1:5, 4:7, 8:9) there is > DW_AT_subrange_type > DW_AT_lower_bound 1 > DW_AT_upper_bound 5 > DW_AT_subrange_type > DW_AT_lower_bound 4 > DW_AT_upper_bound 7 > DW_AT_subrange_type > DW_AT_lower_bound 8 > DW_AT_upper_bound 9 > but GCC doesn't add any DW_AT_ordering, while ifort adds > DW_AT_ordering DW_ORD_col_major. > > Wonder what gdb will do in presence of DW_ORD_col_major, I fear that > DW_ORD_col_major means it just reverses the order of DW_AT_subrange_type > notes and has hardcoded another reordering for Fortran or something, Jan? This is ok if properly tested. Thanks, Richard. > --- gcc/dwarf2out.c.jj 2007-11-15 20:05:54.000000000 +0100 > +++ gcc/dwarf2out.c 2007-11-16 14:16:13.000000000 +0100 > @@ -11636,6 +11636,12 @@ gen_array_type_die (tree type, dw_die_re > add_AT_flag (array_die, DW_AT_GNU_vector, 1); > } > > + /* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */ > + if (is_fortran () > + && TREE_CODE (type) == ARRAY_TYPE > + && TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE) > + add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major); > + > #if 0 > /* We default the array ordering. SDB will probably do > the right things even if DW_AT_ordering is not present. It's not even > @@ -11787,6 +11793,11 @@ gen_descr_array_type_die (tree type, str > add_name_attribute (array_die, type_tag (type)); > equate_type_number_to_die (type, array_die); > > + /* For Fortran multidimensional arrays use DW_ORD_col_major ordering. */ > + if (is_fortran () > + && info->ndimensions >= 2) > + add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major); > + > > if (info->data_location) > add_descr_info_field (array_die, DW_AT_data_location, info->data_location, > info->base_decl); > > Jakub > ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2007-12-09 15:13 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2007-11-12 13:39 [RFC PATCH] Debug support for Fortran 90 assumed shape and other descriptor using arrays (PR fortran/22244) Jakub Jelinek 2007-11-16 11:58 ` [PATCH] " Jakub Jelinek 2007-11-16 13:24 ` Tobias Burnus 2007-11-16 13:28 ` Jakub Jelinek 2007-11-16 14:01 ` Tobias Burnus 2007-11-16 16:14 ` Jakub Jelinek 2007-11-16 18:09 ` Tobias Burnus 2007-11-16 19:05 ` Tobias Burnus 2007-11-16 19:18 ` Jakub Jelinek 2007-11-16 19:05 ` Jakub Jelinek 2007-12-09 15:13 ` Richard Guenther
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).