aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/utils2.c
diff options
context:
space:
mode:
authorThomas Quinot <quinot@adacore.com>2005-11-15 14:53:22 +0100
committerArnaud Charlet <charlet@gcc.gnu.org>2005-11-15 14:53:22 +0100
commit5e61ef090a8910843dd421fad19eae41c4fca816 (patch)
tree539f60872b22a416a9e54b3d9d16de22a8182921 /gcc/ada/utils2.c
parentfda5d6d4ff7de017167de98a20ffc4110f766795 (diff)
downloadgcc-5e61ef090a8910843dd421fad19eae41c4fca816.zip
gcc-5e61ef090a8910843dd421fad19eae41c4fca816.tar.gz
gcc-5e61ef090a8910843dd421fad19eae41c4fca816.tar.bz2
decl.c: Factor common code to build a storage type for an unconstrained object from a...
2005-11-14 Thomas Quinot <quinot@adacore.com> Olivier Hainque <hainque@adacore.com> Eric Botcazou <ebotcazou@adacore.com> * decl.c: Factor common code to build a storage type for an unconstrained object from a fat or thin pointer type and a constrained object type. (annotate_value): Handle BIT_AND_EXPR. (annotate_rep): Don't restrict the back annotation of inherited components to the type_annotate_only case. (gnat_to_gnu_entity) <E_Array_Type>: Do not invoke create_type_decl if we are not defining the type. <E_Record_Type>: Likewise. (gnat_to_gnu_entity) <object, renaming>: Adjust comments and structure to get advantage of the new maybe_stabilize_reference interface, to ensure that what we reference is indeed stabilized instead of relying on assumptions on what the stabilizer does. (gnat_to_gnu_entity) <E_Incomplete_Type>: If the entity is an incomplete type imported through a limited_with clause, use its non-limited view. (Has_Stdcall_Convention): New macro, to centralize the Windows vs others differentiation. (gnat_to_gnu_entity): Use Has_Stdcall_Convention instead of a spread mix of #if sections + explicit comparisons of convention identifiers. (gnat_to_gnu_entity) <E_Variable>: Decrement force_global if necessary before early-returning for certain types when code generation is disabled. (gnat_to_gnu_entity) <object>: Adjust comment attached to the nullification of gnu_expr we do for objects with address clause and that we are not defining. (elaborate_expression_1): Do not create constants when creating variables needed by the debug info: the dwarf2 writer considers that CONST_DECLs is used only to represent enumeration constants, and emits nothing for them. (gnat_to_gnu_entity) <object>: When turning a non-definition of an object with an address clause into an indirect reference, drop the initializing expression. Include "expr.h". (STACK_CHECK_BUILTIN): Delete. (STACK_CHECK_PROBE_INTERVAL): Likewise. (STACK_CHECK_MAX_FRAME_SIZE): Likewise. (STACK_CHECK_MAX_VAR_SIZE): Likewise. (gnat_to_gnu_entity): If gnat_entity is a renaming, do not mark the tree corresponding to the renamed object as ignored for debugging purposes. * trans.c (tree_transform, case N_Attribute_Reference, case Attr_Size & related): For a prefix that is a dereference of a fat or thin pointer, if there is an actual subtype provided by the front-end, use that subtype to build an actual type with bounds template. (tree_transform, case N_Free_Statement): If an Actual_Designated_Subtype is provided by the front-end, use that subtype to compute the size of the deallocated object. (gnat_to_gnu): When adding a statement into an elaboration procedure, check for a potential violation of a No_Elaboration_Code restriction. (maybe_stabilize_reference): New function, like gnat_stabilize_reference with extra arguments to control whether to recurse through non-values and to let the caller know if the stabilization has succeeded. (gnat_stabilize_reference): Now a simple wrapper around maybe_stabilize, for common uses without restriction on lvalues and without need to check for the success indication. (gnat_to_gnu, call_to_gnu): Adjust calls to gnat_stabilize_reference, to pass false instead of 0 as the FORCE argument which is a bool. (Identifier_to_gnu): Remove checks ensuring that an renamed object attached to a renaming pointer has been properly stabilized, as no such object is attached otherwise. (call_to_gnu): Invoke create_var_decl to create the temporary when the function uses the "target pointer" return mechanism. Reinstate conversion of the actual to the type of the formal parameter before any other specific treatment based on the passing mechanism. This turns out to be necessary in order for PLACEHOLDER substitution to work properly when the latter type is unconstrained. * gigi.h (build_unc_object_type_from_ptr): New subprogram, factoring a common pattern. (maybe_stabilize_reference): New function, like gnat_stabilize_reference with extra arguments to control whether to recurse through non-values and to let the caller know if the stabilization has succeeded. * utils2.c (gnat_build_constructor): Only sort the fields for possible static output of record constructor if all the components are constant. (gnat_build_constructor): For a record type, sort the list of field initializers in increasing bit position order. Factor common code to build a storage type for an unconstrained object from a fat or thin pointer type and a constrained object type. (build_unary_op) <ADDR_EXPR>: Always recurse down conversions between types variants, and process special cases of VIEW_CONVERT expressions as their NOP_EXPR counterpart to ensure we get to the CORRESPONDING_VARs associated with CONST_DECls. (build_binary_op) <MODIFY_EXPR>: Do not strip VIEW_CONVERT_EXPRs on the right-hand side. * utils.c (build_unc_object_type_from_ptr): New subprogram, factoring a common pattern. (convert) <VIEW_CONVERT_EXPR>: Return the inner operand directly if we are converting back to its original type. (convert) <JM input>: Fallthrough regular conversion code instead of extracting the object if converting to a type variant. (create_var_decl): When a variable has an initializer requiring code generation and we are at the top level, check for a potential violation of a No_Elaboration_Code restriction. (create_var_decl): call expand_decl for CONST_DECLs, to set MODE, ALIGN SIZE and SIZE_UNIT which we need for later back-annotations. * utils.c: (convert) <STRING_CST>: Remove obsolete code. <VIEW_CONVERT_EXPR>: Do not lift the conversion if the target type is an unchecked union. (pushdecl): Set DECL_NO_STATIC_CHAIN on imported nested functions. (convert) <VIEW_CONVERT_EXPR>: When the types have the same main variant, just replace the VIEW_CONVERT_EXPR. <UNION_TYPE>: Revert 2005-03-02 change. * repinfo.h, repinfo.ads: Add tcode for BIT_AND_EXPR. * repinfo.adb (Print_Expr, Rep_Value): Handle Bit_And_Expressions. From-SVN: r106961
Diffstat (limited to 'gcc/ada/utils2.c')
-rw-r--r--gcc/ada/utils2.c127
1 files changed, 62 insertions, 65 deletions
diff --git a/gcc/ada/utils2.c b/gcc/ada/utils2.c
index 21a3f61..2493744 100644
--- a/gcc/ada/utils2.c
+++ b/gcc/ada/utils2.c
@@ -170,7 +170,7 @@ known_alignment (tree exp)
case NON_LVALUE_EXPR:
/* Conversions between pointers and integers don't change the alignment
of the underlying object. */
- this_alignment = known_alignment (TREE_OPERAND (exp, 0));
+ this_alignment = known_alignment (TREE_OPERAND (exp, 0));
break;
case PLUS_EXPR:
@@ -656,40 +656,6 @@ build_binary_op (enum tree_code op_code, tree result_type,
if (!operation_type)
operation_type = left_type;
- /* If the RHS has a conversion between record and array types and
- an inner type is no worse, use it. Note we cannot do this for
- modular types or types with TYPE_ALIGN_OK, since the latter
- might indicate a conversion between a root type and a class-wide
- type, which we must not remove. */
- while (TREE_CODE (right_operand) == VIEW_CONVERT_EXPR
- && (((TREE_CODE (right_type) == RECORD_TYPE
- || TREE_CODE (right_type) == UNION_TYPE)
- && !TYPE_JUSTIFIED_MODULAR_P (right_type)
- && !TYPE_ALIGN_OK (right_type)
- && !TYPE_IS_FAT_POINTER_P (right_type))
- || TREE_CODE (right_type) == ARRAY_TYPE)
- && ((((TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
- == RECORD_TYPE)
- || (TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
- == UNION_TYPE))
- && !(TYPE_JUSTIFIED_MODULAR_P
- (TREE_TYPE (TREE_OPERAND (right_operand, 0))))
- && !(TYPE_ALIGN_OK
- (TREE_TYPE (TREE_OPERAND (right_operand, 0))))
- && !(TYPE_IS_FAT_POINTER_P
- (TREE_TYPE (TREE_OPERAND (right_operand, 0)))))
- || (TREE_CODE (TREE_TYPE (TREE_OPERAND (right_operand, 0)))
- == ARRAY_TYPE))
- && (0 == (best_type
- = find_common_type (right_type,
- TREE_TYPE (TREE_OPERAND
- (right_operand, 0))))
- || right_type != best_type))
- {
- right_operand = TREE_OPERAND (right_operand, 0);
- right_type = TREE_TYPE (right_operand);
- }
-
/* If we are copying one array or record to another, find the best type
to use. */
if (((TREE_CODE (left_type) == ARRAY_TYPE
@@ -1159,12 +1125,18 @@ build_unary_op (enum tree_code op_code, tree result_type, tree operand)
return build_unary_op (ADDR_EXPR, result_type,
TREE_OPERAND (operand, 0));
- /* If this NOP_EXPR doesn't change the mode, get the result type
- from this type and go down. We need to do this in case
- this is a conversion of a CONST_DECL. */
- if (TYPE_MODE (type) != BLKmode
- && (TYPE_MODE (type)
- == TYPE_MODE (TREE_TYPE (TREE_OPERAND (operand, 0)))))
+ /* ... fallthru ... */
+
+ case VIEW_CONVERT_EXPR:
+ /* If this just a variant conversion or if the conversion doesn't
+ change the mode, get the result type from this type and go down.
+ This is needed for conversions of CONST_DECLs, to eventually get
+ to the address of their CORRESPONDING_VARs. */
+ if ((TYPE_MAIN_VARIANT (type)
+ == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (operand, 0))))
+ || (TYPE_MODE (type) != BLKmode
+ && (TYPE_MODE (type)
+ == TYPE_MODE (TREE_TYPE (TREE_OPERAND (operand, 0))))))
return build_unary_op (ADDR_EXPR,
(result_type ? result_type
: build_pointer_type (type)),
@@ -1409,7 +1381,7 @@ build_return_expr (tree result_decl, tree ret_val)
build_binary_op with the additional guarantee that the type
cannot involve a placeholder, since otherwise the function
would use the "target pointer" return mechanism. */
-
+
if (operation_type != TREE_TYPE (ret_val))
ret_val = convert (operation_type, ret_val);
@@ -1493,17 +1465,41 @@ build_call_raise (int msg)
build_int_cst (NULL_TREE, input_line));
}
+/* qsort comparer for the bit positions of two constructor elements
+ for record components. */
+
+static int
+compare_elmt_bitpos (const PTR rt1, const PTR rt2)
+{
+ tree elmt1 = * (tree *) rt1;
+ tree elmt2 = * (tree *) rt2;
+
+ tree pos_field1 = bit_position (TREE_PURPOSE (elmt1));
+ tree pos_field2 = bit_position (TREE_PURPOSE (elmt2));
+
+ if (tree_int_cst_equal (pos_field1, pos_field2))
+ return 0;
+ else if (tree_int_cst_lt (pos_field1, pos_field2))
+ return -1;
+ else
+ return 1;
+}
+
/* Return a CONSTRUCTOR of TYPE whose list is LIST. */
tree
gnat_build_constructor (tree type, tree list)
{
tree elmt;
+ int n_elmts;
bool allconstant = (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST);
bool side_effects = false;
tree result;
- for (elmt = list; elmt; elmt = TREE_CHAIN (elmt))
+ /* Scan the elements to see if they are all constant or if any has side
+ effects, to let us set global flags on the resulting constructor. Count
+ the elements along the way for possible sorting purposes below. */
+ for (n_elmts = 0, elmt = list; elmt; elmt = TREE_CHAIN (elmt), n_elmts ++)
{
if (!TREE_CONSTANT (TREE_VALUE (elmt))
|| (TREE_CODE (type) == RECORD_TYPE
@@ -1525,26 +1521,30 @@ gnat_build_constructor (tree type, tree list)
return build1 (NULL_EXPR, type, TREE_OPERAND (result, 0));
}
- /* If TYPE is a RECORD_TYPE and the fields are not in the
- same order as their bit position, don't treat this as constant
- since varasm.c can't handle it. */
- if (allconstant && TREE_CODE (type) == RECORD_TYPE)
+ /* For record types with constant components only, sort field list
+ by increasing bit position. This is necessary to ensure the
+ constructor can be output as static data, which the gimplifier
+ might force in various circumstances. */
+ if (allconstant && TREE_CODE (type) == RECORD_TYPE && n_elmts > 1)
{
- tree last_pos = bitsize_zero_node;
- tree field;
+ /* Fill an array with an element tree per index, and ask qsort to order
+ them according to what a bitpos comparison function says. */
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- {
- tree this_pos = bit_position (field);
+ tree *gnu_arr = (tree *) alloca (sizeof (tree) * n_elmts);
+ int i;
- if (TREE_CODE (this_pos) != INTEGER_CST
- || tree_int_cst_lt (this_pos, last_pos))
- {
- allconstant = false;
- break;
- }
+ for (i = 0, elmt = list; elmt; elmt = TREE_CHAIN (elmt), i++)
+ gnu_arr[i] = elmt;
+
+ qsort (gnu_arr, n_elmts, sizeof (tree), compare_elmt_bitpos);
- last_pos = this_pos;
+ /* Then reconstruct the list from the sorted array contents. */
+
+ list = NULL_TREE;
+ for (i = n_elmts - 1; i >= 0; i--)
+ {
+ TREE_CHAIN (gnu_arr[i]) = list;
+ list = gnu_arr[i];
}
}
@@ -1821,13 +1821,10 @@ build_allocator (tree type, tree init, tree result_type, Entity_Id gnat_proc,
fill in the parts that are known. */
else if (TYPE_FAT_OR_THIN_POINTER_P (result_type))
{
- tree template_type
- = (TYPE_FAT_POINTER_P (result_type)
- ? TREE_TYPE (TREE_TYPE (TREE_CHAIN (TYPE_FIELDS (result_type))))
- : TREE_TYPE (TYPE_FIELDS (TREE_TYPE (result_type))));
tree storage_type
- = build_unc_object_type (template_type, type,
- get_identifier ("ALLOC"));
+ = build_unc_object_type_from_ptr (result_type, type,
+ get_identifier ("ALLOC"));
+ tree template_type = TREE_TYPE (TYPE_FIELDS (storage_type));
tree storage_ptr_type = build_pointer_type (storage_type);
tree storage;
tree template_cons = NULL_TREE;