+2015-12-17 Pierre-Marie de Rodat <derodat@adacore.com>
+
+ * gcc-interface/ada-tree.h
+ (TYPE_IMPLEMENTS_PACKED_ARRAY_P, TYPE_CAN_HAVE_DEBUG_TYPE_P,
+ TYPE_ORIGINAL_PACKED_ARRAY, SET_TYPE_ORIGINAL_PACKED_ARRAY): New
+ macros.
+ * gcc-interface/decl.c (add_parallel_type_for_packed_array):
+ Rename to associate_original_type_to_packed_array. When
+ -fgnat-encodings=minimal, set original packed array type as so
+ instead of as a parallel type to the implementation type. In
+ this case, also rename the implementation type to the name of
+ the original array type.
+ (gnat_to_gnu_entity): Update invocations to
+ add_parallel_type_for_packed_array. Tag ARRAY_TYPE nodes for
+ packed arrays with the TYPE_PACKED flag.
+ When -fgnat-encodings=minimal:
+ - strip ___XP suffixes in packed arrays' names;
+ - set the debug type for padding records around packed arrays
+ to the packed array;
+ - do not attach ___XUP types as parallel types of constrained
+ array types.
+ * gcc-interface/misc.c (gnat_print_type): Update to handle
+ orignal packed arrays.
+ (gnat_get_debug_type): Update to reject packed arrays
+ implementation types.
+ (get_array_bit_stride): New.
+ (gnat_get_array_descr_info): Add packed arrays handling.
+ * gcc-interface/utils.c (maybe_pad_type): When
+ -fgnat-encodings=minimal, set the name of the padding type to
+ the one of the original packed type, if any. Fix TYPE_DECL
+ peeling around the name of the input type.
+
2015-12-17 Pierre-Marie de Rodat <derodat@adacore.com>
* gcc-interface/misc.c (gnat_get_type_bias): New.
alignment value the type ought to have. */
#define TYPE_MAX_ALIGN(NODE) (TYPE_PRECISION (RECORD_OR_UNION_CHECK (NODE)))
+/* True for types that implement a packed array and for original packed array
+ types. */
+#define TYPE_IMPLEMENTS_PACKED_ARRAY_P(NODE) \
+ ((TREE_CODE (NODE) == ARRAY_TYPE && TYPE_PACKED (NODE)) \
+ || (TREE_CODE (NODE) == INTEGER_TYPE && TYPE_PACKED_ARRAY_TYPE_P (NODE))) \
+
+/* True for types that can hold a debug type. */
+#define TYPE_CAN_HAVE_DEBUG_TYPE_P(NODE) \
+ (!TYPE_IMPLEMENTS_PACKED_ARRAY_P (NODE) \
+ && TYPE_DEBUG_TYPE (NODE) != NULL_TREE)
+
/* For an UNCONSTRAINED_ARRAY_TYPE, this is the record containing both the
template and the object.
#define SET_TYPE_SCALE_FACTOR(NODE, X) \
SET_TYPE_LANG_SPECIFIC (INTEGER_TYPE_CHECK (NODE), X)
+/* For types with TYPE_CAN_HAVE_DEBUG_TYPE_P, this is the type to use in
+ debugging information. */
+#define TYPE_DEBUG_TYPE(NODE) \
+ GET_TYPE_LANG_SPECIFIC2(NODE)
+#define SET_TYPE_DEBUG_TYPE(NODE, X) \
+ SET_TYPE_LANG_SPECIFIC2(NODE, X)
+
+/* For types with TYPE_IMPLEMENTS_PACKED_ARRAY_P, this is the original packed
+ array type. Note that this predicate is trou for original packed array
+ types, so these cannot have a debug type. */
+#define TYPE_ORIGINAL_PACKED_ARRAY(NODE) \
+ GET_TYPE_LANG_SPECIFIC2(NODE)
+#define SET_TYPE_ORIGINAL_PACKED_ARRAY(NODE, X) \
+ SET_TYPE_LANG_SPECIFIC2(NODE, X)
+
/* Flags added to decl nodes. */
static tree create_variant_part_from (tree, vec<variant_desc> , tree,
tree, vec<subst_pair> );
static void copy_and_substitute_in_size (tree, tree, vec<subst_pair> );
-static void add_parallel_type_for_packed_array (tree, Entity_Id);
+static void associate_original_type_to_packed_array (tree, Entity_Id);
static const char *get_entity_char (Entity_Id);
/* The relevant constituents of a subprogram binding to a GCC builtin. Used
TYPE_STUB_DECL (gnu_type)
= create_type_stub_decl (gnu_entity_name, gnu_type);
- /* For a packed array, make the original array type a parallel type. */
+ /* For a packed array, make the original array type a parallel/debug
+ type. */
if (debug_info_p && Is_Packed_Array_Impl_Type (gnat_entity))
- add_parallel_type_for_packed_array (gnu_type, gnat_entity);
+ associate_original_type_to_packed_array (gnu_type, gnat_entity);
discrete_type:
UI_To_gnu (RM_Size (gnat_entity), bitsizetype));
TYPE_PACKED_ARRAY_TYPE_P (gnu_type) = 1;
+ /* Strip the ___XP suffix for standard DWARF. */
+ if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
+ gnu_entity_name = TYPE_NAME (gnu_type);
+
/* Create a stripped-down declaration, mainly for debugging. */
create_type_decl (gnu_entity_name, gnu_type, true, debug_info_p,
gnat_entity);
if (debug_info_p)
{
- /* Make the original array type a parallel type. */
- add_parallel_type_for_packed_array (gnu_type, gnat_entity);
+ /* Make the original array type a parallel/debug type. */
+ associate_original_type_to_packed_array (gnu_type, gnat_entity);
+
+ /* Since GNU_TYPE is a padding type around the packed array
+ implementation type, the padded type is its debug type. */
+ if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
+ SET_TYPE_DEBUG_TYPE (gnu_type, gnu_field_type);
rest_of_record_type_compilation (gnu_type);
}
TYPE_CONVENTION_FORTRAN_P (tem) = convention_fortran_p;
+ /* Tag top-level ARRAY_TYPE nodes for packed arrays and their
+ implementation types as such so that the debug information back-end
+ can output the appropriate description for them. */
+ TYPE_PACKED (tem)
+ = (Is_Packed (gnat_entity)
+ || Is_Packed_Array_Impl_Type (gnat_entity));
+
if (Treat_As_Volatile (gnat_entity))
tem = change_qualified_type (tem, TYPE_QUAL_VOLATILE);
TYPE_NONALIASED_COMPONENT (gnu_type) = 1;
}
+ /* Strip the ___XP suffix for standard DWARF. */
+ if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL
+ && Is_Packed_Array_Impl_Type (gnat_entity))
+ {
+ Entity_Id gnat_original_array_type
+ = Underlying_Type (Original_Array_Type (gnat_entity));
+
+ gnu_entity_name
+ = get_entity_name (gnat_original_array_type);
+ }
+
/* Attach the TYPE_STUB_DECL in case we have a parallel type. */
TYPE_STUB_DECL (gnu_type)
= create_type_stub_decl (gnu_entity_name, gnu_type);
}
/* If this is a packed array type, make the original array type a
- parallel type. Otherwise, do it for the base array type if it
- isn't artificial to make sure it is kept in the debug info. */
+ parallel/debug type. Otherwise, if such GNAT encodings are
+ required, do it for the base array type if it isn't artificial to
+ make sure it is kept in the debug info. */
if (debug_info_p)
{
if (Is_Packed_Array_Impl_Type (gnat_entity))
- add_parallel_type_for_packed_array (gnu_type, gnat_entity);
+ associate_original_type_to_packed_array (gnu_type,
+ gnat_entity);
else
{
tree gnu_base_decl
= gnat_to_gnu_entity (Etype (gnat_entity), NULL_TREE, 0);
- if (!DECL_ARTIFICIAL (gnu_base_decl))
+ if (gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL
+ && !DECL_ARTIFICIAL (gnu_base_decl))
add_parallel_type (gnu_type,
TREE_TYPE (TREE_TYPE (gnu_base_decl)));
}
= (Is_Packed_Array_Impl_Type (gnat_entity)
&& Is_Bit_Packed_Array (Original_Array_Type (gnat_entity)));
+ /* Tag top-level ARRAY_TYPE nodes for packed arrays and their
+ implementation types as such so that the debug information back-end
+ can output the appropriate description for them. */
+ TYPE_PACKED (gnu_type)
+ = (Is_Packed (gnat_entity)
+ || Is_Packed_Array_Impl_Type (gnat_entity));
+
/* If the size is self-referential and the maximum size doesn't
overflow, use it. */
if (CONTAINS_PLACEHOLDER_P (TYPE_SIZE (gnu_type))
NULL_TREE, 0);
this_made_decl = true;
gnu_type = TREE_TYPE (gnu_decl);
+
save_gnu_tree (gnat_entity, NULL_TREE, false);
gnu_inner = gnu_type;
TYPE_SIZE_UNIT (new_type) = variable_size (TYPE_SIZE_UNIT (new_type));
}
-/* Add a parallel type to GNU_TYPE, the translation of GNAT_ENTITY, which is
- the implementation type of a packed array type (Is_Packed_Array_Impl_Type).
- The parallel type is the original array type if it has been translated. */
+/* Associate to GNU_TYPE, the translation of GNAT_ENTITY, which is
+ the implementation type of a packed array type (Is_Packed_Array_Impl_Type),
+ the original array type if it has been translated. This association is a
+ parallel type for GNAT encodings or a debug type for standard DWARF. Note
+ that for standard DWARF, we also want to get the original type name. */
static void
-add_parallel_type_for_packed_array (tree gnu_type, Entity_Id gnat_entity)
+associate_original_type_to_packed_array (tree gnu_type, Entity_Id gnat_entity)
{
Entity_Id gnat_original_array_type
= Underlying_Type (Original_Array_Type (gnat_entity));
if (TYPE_IS_DUMMY_P (gnu_original_array_type))
return;
- add_parallel_type (gnu_type, gnu_original_array_type);
+ if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
+ {
+ tree original_name = TYPE_NAME (gnu_original_array_type);
+
+ if (TREE_CODE (original_name) == TYPE_DECL)
+ original_name = DECL_NAME (original_name);
+
+ SET_TYPE_ORIGINAL_PACKED_ARRAY (gnu_type, gnu_original_array_type);
+ TYPE_NAME (gnu_type) = original_name;
+ }
+ else
+ add_parallel_type (gnu_type, gnu_original_array_type);
}
\f
/* Given a type T, a FIELD_DECL F, and a replacement value R, return a
break;
}
- if (TYPE_DEBUG_TYPE (node) != NULL_TREE)
- print_node_brief (file, "debug type", TYPE_DEBUG_TYPE (node),
- indent + 4);
+ if (TYPE_CAN_HAVE_DEBUG_TYPE_P (node) && TYPE_DEBUG_TYPE (node) != NULL_TREE)
+ print_node_brief (file, "debug type", TYPE_DEBUG_TYPE (node), indent + 4);
+ else if (TYPE_IMPLEMENTS_PACKED_ARRAY_P (node)
+ && TYPE_ORIGINAL_PACKED_ARRAY (node) != NULL_TREE)
+ print_node_brief (file, "original packed array",
+ TYPE_ORIGINAL_PACKED_ARRAY (node), indent + 4);
}
/* Return the name to be printed for DECL. */
static tree
gnat_get_debug_type (const_tree type)
{
- return TYPE_DEBUG_TYPE (type);
+ if (TYPE_CAN_HAVE_DEBUG_TYPE_P (type))
+ {
+ type = TYPE_DEBUG_TYPE (type);
+ /* ??? Kludge: the get_debug_type language hook is processed after the
+ array descriptor language hook, so if there is an array behind this
+ type, the latter is supposed to handle it. Still, we can get here
+ with a type we are not supposed to handle (when the DWARF back-end
+ processes the type of a variable), so keep this guard. */
+ if (type != NULL_TREE && !TYPE_IMPLEMENTS_PACKED_ARRAY_P (type))
+ return const_cast<tree> (type);
+ }
+ return NULL_TREE;
}
/* Provide information in INFO for debugging output about the TYPE fixed-point
return max_unitsize;
}
+static tree get_array_bit_stride (tree comp_type);
+
/* Provide information in INFO for debug output about the TYPE array type.
Return whether TYPE is handled. */
static bool
-gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
+gnat_get_array_descr_info (const_tree const_type,
+ struct array_descr_info *info)
{
bool convention_fortran_p;
bool is_array = false;
bool is_fat_ptr = false;
+ bool is_packed_array = false;
- const tree type_ = const_cast<tree> (type);
+ tree type = const_cast<tree> (const_type);
const_tree first_dimen = NULL_TREE;
const_tree last_dimen = NULL_TREE;
tree thinptr_template_expr = NULL_TREE;
tree thinptr_bound_field = NULL_TREE;
+ /* ??? Kludge: see gnat_get_debug_type. */
+ if (TYPE_CAN_HAVE_DEBUG_TYPE_P (type)
+ && TYPE_DEBUG_TYPE (type) != NULL_TREE)
+ type = TYPE_DEBUG_TYPE (type);
+
+ /* If we have an implementation type for a packed array, get the orignial
+ array type. */
+ if (TYPE_IMPLEMENTS_PACKED_ARRAY_P (type)
+ && TYPE_ORIGINAL_PACKED_ARRAY (type) != NULL_TREE)
+ {
+ is_packed_array = true;
+ type = TYPE_ORIGINAL_PACKED_ARRAY (type);
+ }
+
/* First pass: gather all information about this array except everything
related to dimensions. */
else if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL
&& TYPE_IS_FAT_POINTER_P (type))
{
- const tree ua_type = TYPE_UNCONSTRAINED_ARRAY (type_);
+ const tree ua_type = TYPE_UNCONSTRAINED_ARRAY (type);
/* This will be our base object address. */
- const tree placeholder_expr = build0 (PLACEHOLDER_EXPR, type_);
+ const tree placeholder_expr = build0 (PLACEHOLDER_EXPR, type);
/* We assume below that maybe_unconstrained_array returns an INDIRECT_REF
node. */
/* This will be our base object address. Note that we assume that
pointers to these will actually point to the array field (thin
pointers are shifted). */
- const tree placeholder_expr = build0 (PLACEHOLDER_EXPR, type_);
+ const tree placeholder_expr = build0 (PLACEHOLDER_EXPR, type);
const tree placeholder_addr
= build_unary_op (ADDR_EXPR, NULL_TREE, placeholder_expr);
/* Second pass: compute the remaining information: dimensions and
corresponding bounds. */
+ if (TYPE_PACKED (first_dimen))
+ is_packed_array = true;
/* If this array has fortran convention, it's arranged in column-major
order, so our view here has reversed dimensions. */
convention_fortran_p = TYPE_CONVENTION_FORTRAN_P (first_dimen);
info->allocated = NULL_TREE;
info->associated = NULL_TREE;
- /* When arrays contain dynamically-sized elements, we usually wrap them in
- padding types, or we create constrained types for them. Then, if such
- types are stripped in the debugging information output, the debugger needs
- a way to know the size that is reserved for each element. This is why we
- emit a stride in such situations. */
if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
{
+ /* When arrays contain dynamically-sized elements, we usually wrap them
+ in padding types, or we create constrained types for them. Then, if
+ such types are stripped in the debugging information output, the
+ debugger needs a way to know the size that is reserved for each
+ element. This is why we emit a stride in such situations. */
tree source_element_type = info->element_type;
while (1)
info->stride = TYPE_SIZE_UNIT (info->element_type);
info->stride_in_bits = false;
}
+
+ /* We need to specify a bit stride when it does not correspond to the
+ natural size of the contained elements. ??? Note that we do not
+ support packed records and nested packed arrays. */
+ else if (is_packed_array)
+ {
+ info->stride = get_array_bit_stride (info->element_type);
+ info->stride_in_bits = true;
+ }
}
return true;
}
+/* Given the component type COMP_TYPE of a packed array, return an expression
+ that computes the bit stride of this packed array. Return NULL_TREE when
+ unsuccessful. */
+
+static tree
+get_array_bit_stride (tree comp_type)
+{
+ struct array_descr_info info;
+ tree stride;
+
+ /* Simple case: the array contains an integral type: return its RM size. */
+ if (INTEGRAL_TYPE_P (comp_type))
+ return TYPE_RM_SIZE (comp_type);
+
+ /* Otherwise, see if this is an array we can analyze. */
+ memset (&info, 0, sizeof (info));
+ if (!gnat_get_array_descr_info (comp_type, &info)
+ || info.stride == NULL_TREE)
+ /* If it's not, give it up. */
+ return NULL_TREE;
+
+ /* Otherwise, the array stride is the inner array's stride multiplied by the
+ number of elements it contains. Note that if the inner array is not
+ packed, then the stride is "natural" and thus does not deserve an
+ attribute. */
+ stride = info.stride;
+ if (!info.stride_in_bits)
+ {
+ stride = fold_convert (bitsizetype, stride);
+ stride = build_binary_op (MULT_EXPR, bitsizetype,
+ stride, build_int_cstu (bitsizetype, 8));
+ }
+
+ for (int i = 0; i < info.ndimensions; ++i)
+ {
+ tree count;
+
+ if (info.dimen[i].lower_bound == NULL_TREE
+ || info.dimen[i].upper_bound == NULL_TREE)
+ return NULL_TREE;
+
+ /* Put in count an expression that computes the length of this
+ dimension. */
+ count = build_binary_op (MINUS_EXPR, sbitsizetype,
+ fold_convert (sbitsizetype,
+ info.dimen[i].upper_bound),
+ fold_convert (sbitsizetype,
+ info.dimen[i].lower_bound)),
+ count = build_binary_op (PLUS_EXPR, sbitsizetype,
+ count, build_int_cstu (sbitsizetype, 1));
+ count = build_binary_op (MAX_EXPR, sbitsizetype,
+ count,
+ build_int_cstu (sbitsizetype, 0));
+ count = fold_convert (bitsizetype, count);
+ stride = build_binary_op (MULT_EXPR, bitsizetype, stride, count);
+ }
+
+ return stride;
+}
+
/* GNU_TYPE is a subtype of an integral type. Set LOWVAL to the low bound
and HIGHVAL to the high bound, respectively. */
if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL)
SET_TYPE_DEBUG_TYPE (record, type);
- if (Present (gnat_entity))
+ /* ??? Kludge: padding types around packed array implementation types will be
+ considered as root types in the array descriptor language hook (see
+ gnat_get_array_descr_info). Give them the original packed array type
+ name so that the one coming from sources appears in the debugging
+ information. */
+ if (gnat_encodings == DWARF_GNAT_ENCODINGS_MINIMAL
+ && TYPE_IMPLEMENTS_PACKED_ARRAY_P (type)
+ && TYPE_ORIGINAL_PACKED_ARRAY (type) != NULL_TREE)
+ TYPE_NAME (record)
+ = TYPE_NAME (TYPE_ORIGINAL_PACKED_ARRAY (type));
+ else if (Present (gnat_entity))
TYPE_NAME (record) = create_concat_name (gnat_entity, "PAD");
TYPE_ALIGN (record) = align ? align : orig_align;