diff options
Diffstat (limited to 'gcc/ada/gcc-interface/utils.c')
-rw-r--r-- | gcc/ada/gcc-interface/utils.c | 90 |
1 files changed, 28 insertions, 62 deletions
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 80c0716..7217eea 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -288,7 +288,6 @@ static tree split_plus (tree, tree *); static tree float_type_for_precision (int, machine_mode); static tree convert_to_fat_pointer (tree, tree); static unsigned int scale_by_factor_of (tree, unsigned int); -static bool potential_alignment_gap (tree, tree, tree); /* Linked list used as a queue to defer the initialization of the DECL_CONTEXT of ..._DECL nodes and of the TYPE_CONTEXT of ..._TYPE nodes. */ @@ -2171,7 +2170,6 @@ rest_of_record_type_compilation (tree record_type) ? UNION_TYPE : TREE_CODE (record_type)); tree orig_name = TYPE_IDENTIFIER (record_type), new_name; tree last_pos = bitsize_zero_node; - tree old_field, prev_old_field = NULL_TREE; new_name = concat_name (orig_name, TREE_CODE (record_type) == QUAL_UNION_TYPE @@ -2189,7 +2187,8 @@ rest_of_record_type_compilation (tree record_type) /* Now scan all the fields, replacing each field with a new field corresponding to the new encoding. */ - for (old_field = TYPE_FIELDS (record_type); old_field; + for (tree old_field = TYPE_FIELDS (record_type); + old_field; old_field = DECL_CHAIN (old_field)) { tree field_type = TREE_TYPE (old_field); @@ -2213,9 +2212,10 @@ rest_of_record_type_compilation (tree record_type) else pos = compute_related_constant (curpos, last_pos); - if (!pos - && TREE_CODE (curpos) == MULT_EXPR - && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1))) + if (pos) + ; + else if (TREE_CODE (curpos) == MULT_EXPR + && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1))) { tree offset = TREE_OPERAND (curpos, 0); align = tree_to_uhwi (TREE_OPERAND (curpos, 1)); @@ -2223,8 +2223,7 @@ rest_of_record_type_compilation (tree record_type) last_pos = round_up (last_pos, align); pos = compute_related_constant (curpos, last_pos); } - else if (!pos - && TREE_CODE (curpos) == PLUS_EXPR + else if (TREE_CODE (curpos) == PLUS_EXPR && tree_fits_uhwi_p (TREE_OPERAND (curpos, 1)) && TREE_CODE (TREE_OPERAND (curpos, 0)) == MULT_EXPR && tree_fits_uhwi_p @@ -2240,9 +2239,9 @@ rest_of_record_type_compilation (tree record_type) last_pos = round_up (last_pos, align); pos = compute_related_constant (curpos, last_pos); } - else if (potential_alignment_gap (prev_old_field, old_field, pos)) + else { - align = TYPE_ALIGN (field_type); + align = DECL_ALIGN (old_field); last_pos = round_up (last_pos, align); pos = compute_related_constant (curpos, last_pos); } @@ -2261,13 +2260,17 @@ rest_of_record_type_compilation (tree record_type) in this case, if we don't preventively counter that. */ if (TREE_CODE (DECL_SIZE (old_field)) != INTEGER_CST) { - field_type = build_pointer_type (field_type); - if (align != 0 && TYPE_ALIGN (field_type) > align) + field_type = copy_type (build_pointer_type (field_type)); + SET_TYPE_ALIGN (field_type, BITS_PER_UNIT); + var = true; + + /* ??? Kludge to work around a bug in Workbench's debugger. */ + if (align == 0) { - field_type = copy_type (field_type); - SET_TYPE_ALIGN (field_type, align); + align = DECL_ALIGN (old_field); + last_pos = round_up (last_pos, align); + pos = compute_related_constant (curpos, last_pos); } - var = true; } /* Make a new field name, if necessary. */ @@ -2287,6 +2290,16 @@ rest_of_record_type_compilation (tree record_type) new_field = create_field_decl (field_name, field_type, new_record_type, DECL_SIZE (old_field), pos, 0, 0); + /* The specified position is not the actual position of the field + but the gap with the previous field, so the computation of the + bit-field status may be incorrect. We adjust it manually to + avoid generating useless attributes for the field in DWARF. */ + if (DECL_SIZE (old_field) == TYPE_SIZE (field_type) + && value_factor_p (pos, BITS_PER_UNIT)) + { + DECL_BIT_FIELD (new_field) = 0; + DECL_BIT_FIELD_TYPE (new_field) = NULL_TREE; + } DECL_CHAIN (new_field) = TYPE_FIELDS (new_record_type); TYPE_FIELDS (new_record_type) = new_field; @@ -2300,7 +2313,6 @@ rest_of_record_type_compilation (tree record_type) == QUAL_UNION_TYPE) ? bitsize_zero_node : DECL_SIZE (old_field)); - prev_old_field = old_field; } TYPE_FIELDS (new_record_type) = nreverse (TYPE_FIELDS (new_record_type)); @@ -3260,52 +3272,6 @@ scale_by_factor_of (tree expr, unsigned int value) return factor * value; } -/* Given two consecutive field decls PREV_FIELD and CURR_FIELD, return true - unless we can prove these 2 fields are laid out in such a way that no gap - exist between the end of PREV_FIELD and the beginning of CURR_FIELD. OFFSET - is the distance in bits between the end of PREV_FIELD and the starting - position of CURR_FIELD. It is ignored if null. */ - -static bool -potential_alignment_gap (tree prev_field, tree curr_field, tree offset) -{ - /* If this is the first field of the record, there cannot be any gap */ - if (!prev_field) - return false; - - /* If the previous field is a union type, then return false: The only - time when such a field is not the last field of the record is when - there are other components at fixed positions after it (meaning there - was a rep clause for every field), in which case we don't want the - alignment constraint to override them. */ - if (TREE_CODE (TREE_TYPE (prev_field)) == QUAL_UNION_TYPE) - return false; - - /* If the distance between the end of prev_field and the beginning of - curr_field is constant, then there is a gap if the value of this - constant is not null. */ - if (offset && tree_fits_uhwi_p (offset)) - return !integer_zerop (offset); - - /* If the size and position of the previous field are constant, - then check the sum of this size and position. There will be a gap - iff it is not multiple of the current field alignment. */ - if (tree_fits_uhwi_p (DECL_SIZE (prev_field)) - && tree_fits_uhwi_p (bit_position (prev_field))) - return ((tree_to_uhwi (bit_position (prev_field)) - + tree_to_uhwi (DECL_SIZE (prev_field))) - % DECL_ALIGN (curr_field) != 0); - - /* If both the position and size of the previous field are multiples - of the current field alignment, there cannot be any gap. */ - if (value_factor_p (bit_position (prev_field), DECL_ALIGN (curr_field)) - && value_factor_p (DECL_SIZE (prev_field), DECL_ALIGN (curr_field))) - return false; - - /* Fallback, return that there may be a potential gap */ - return true; -} - /* Return a LABEL_DECL with NAME. GNAT_NODE is used for the position of the decl. */ |