summaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-types.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-types.c')
-rw-r--r--gcc/fortran/trans-types.c1485
1 files changed, 1485 insertions, 0 deletions
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
new file mode 100644
index 00000000000..12943891582
--- /dev/null
+++ b/gcc/fortran/trans-types.c
@@ -0,0 +1,1485 @@
+/* Backend support for Fortran 95 basic types and derived types.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Contributed by Paul Brook <paul@nowt.org>
+ and Steven Bosscher <s.bosscher@student.tudelft.nl>
+
+This file is part of GNU G95.
+
+GNU G95 is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU G95 is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU G95; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* trans-types.c -- gfortran backend types */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include <stdio.h>
+#include "ggc.h"
+#include "toplev.h"
+#include <assert.h>
+#include "gfortran.h"
+#include "trans.h"
+#include "trans-types.h"
+#include "trans-const.h"
+
+
+#if (GFC_MAX_DIMENSIONS < 10)
+#define GFC_RANK_DIGITS 1
+#define GFC_RANK_PRINTF_FORMAT "%01d"
+#elif (GFC_MAX_DIMENSIONS < 100)
+#define GFC_RANK_DIGITS 2
+#define GFC_RANK_PRINTF_FORMAT "%02d"
+#else
+#error If you really need >99 dimensions, continue the sequence above...
+#endif
+
+static tree gfc_get_derived_type (gfc_symbol * derived);
+
+tree gfc_type_nodes[NUM_F95_TYPES];
+
+tree gfc_array_index_type;
+tree pvoid_type_node;
+tree ppvoid_type_node;
+tree pchar_type_node;
+
+static GTY(()) tree gfc_desc_dim_type = NULL;
+
+static GTY(()) tree gfc_max_array_element_size;
+
+/* Create the backend type nodes. We map them to their
+ equivalent C type, at least for now. We also give
+ names to the types here, and we push them in the
+ global binding level context.*/
+void
+gfc_init_types (void)
+{
+ unsigned n;
+ unsigned HOST_WIDE_INT hi;
+ unsigned HOST_WIDE_INT lo;
+
+ /* Name the types. */
+#define PUSH_TYPE(name, node) \
+ pushdecl (build_decl (TYPE_DECL, get_identifier (name), node))
+
+ gfc_int1_type_node = signed_char_type_node;
+ PUSH_TYPE ("int1", gfc_int1_type_node);
+ gfc_int2_type_node = short_integer_type_node;
+ PUSH_TYPE ("int2", gfc_int2_type_node);
+ gfc_int4_type_node = gfc_type_for_size (32, 0 /*unsigned */ );
+ PUSH_TYPE ("int4", gfc_int4_type_node);
+ gfc_int8_type_node = gfc_type_for_size (64, 0 /*unsigned */ );
+ PUSH_TYPE ("int8", gfc_int8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ gfc_int16_type_node = gfc_type_for_size (128, 0 /*unsigned */ );
+ PUSH_TYPE ("int16", gfc_int16_type_node);
+#endif
+
+ gfc_real4_type_node = float_type_node;
+ PUSH_TYPE ("real4", gfc_real4_type_node);
+ gfc_real8_type_node = double_type_node;
+ PUSH_TYPE ("real8", gfc_real8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ /* Hmm, this will not work. Ref. g77 */
+ gfc_real16_type_node = long_double_type_node;
+ PUSH_TYPE ("real16", gfc_real16_type_node);
+#endif
+
+ gfc_complex4_type_node = complex_float_type_node;
+ PUSH_TYPE ("complex4", gfc_complex4_type_node);
+ gfc_complex8_type_node = complex_double_type_node;
+ PUSH_TYPE ("complex8", gfc_complex8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ /* Hmm, this will not work. Ref. g77 */
+ gfc_complex16_type_node = complex_long_double_type_node;
+ PUSH_TYPE ("complex16", gfc_complex16_type_node);
+#endif
+
+ gfc_logical1_type_node = make_node (BOOLEAN_TYPE);
+ TYPE_PRECISION (gfc_logical1_type_node) = 8;
+ fixup_unsigned_type (gfc_logical1_type_node);
+ PUSH_TYPE ("logical1", gfc_logical1_type_node);
+ gfc_logical2_type_node = make_node (BOOLEAN_TYPE);
+ TYPE_PRECISION (gfc_logical2_type_node) = 16;
+ fixup_unsigned_type (gfc_logical2_type_node);
+ PUSH_TYPE ("logical2", gfc_logical2_type_node);
+ gfc_logical4_type_node = make_node (BOOLEAN_TYPE);
+ TYPE_PRECISION (gfc_logical4_type_node) = 32;
+ fixup_unsigned_type (gfc_logical4_type_node);
+ PUSH_TYPE ("logical4", gfc_logical4_type_node);
+ gfc_logical8_type_node = make_node (BOOLEAN_TYPE);
+ TYPE_PRECISION (gfc_logical8_type_node) = 64;
+ fixup_unsigned_type (gfc_logical8_type_node);
+ PUSH_TYPE ("logical8", gfc_logical8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ gfc_logical16_type_node = make_node (BOOLEAN_TYPE);
+ TYPE_PRECISION (gfc_logical16_type_node) = 128;
+ fixup_unsigned_type (gfc_logical16_type_node);
+ PUSH_TYPE ("logical16", gfc_logical16_type_node);
+#endif
+
+ gfc_character1_type_node = build_type_variant (signed_char_type_node, 0, 0);
+ PUSH_TYPE ("char", gfc_character1_type_node);
+
+ PUSH_TYPE ("byte", unsigned_char_type_node);
+ PUSH_TYPE ("void", void_type_node);
+
+ /* DBX debugging output gets upset if these aren't set. */
+ if (!TYPE_NAME (integer_type_node))
+ PUSH_TYPE ("c_integer", integer_type_node);
+ if (!TYPE_NAME (char_type_node))
+ PUSH_TYPE ("c_char", char_type_node);
+#undef PUSH_TYPE
+
+ pvoid_type_node = build_pointer_type (void_type_node);
+ ppvoid_type_node = build_pointer_type (pvoid_type_node);
+ pchar_type_node = build_pointer_type (gfc_character1_type_node);
+
+ gfc_index_integer_kind = TYPE_PRECISION (long_unsigned_type_node) / 8;
+ gfc_array_index_type = gfc_get_int_type (gfc_index_integer_kind);
+
+ /* The maximum array element size that can be handled is determined
+ by the number of bits available to store this field in the array
+ descriptor. */
+
+ n = TREE_INT_CST_LOW (TYPE_SIZE (gfc_array_index_type))
+ - GFC_DTYPE_SIZE_SHIFT;
+
+ if (n > sizeof (HOST_WIDE_INT) * 8)
+ {
+ lo = ~(unsigned HOST_WIDE_INT) 0;
+ hi = lo >> (sizeof (HOST_WIDE_INT) * 16 - n);
+ }
+ else
+ {
+ hi = 0;
+ lo = (~(unsigned HOST_WIDE_INT) 0) >> (sizeof (HOST_WIDE_INT) * 8 - n);
+ }
+ gfc_max_array_element_size = build_int_2 (lo, hi);
+ TREE_TYPE (gfc_max_array_element_size) = long_unsigned_type_node;
+
+ size_type_node = gfc_array_index_type;
+ boolean_type_node = gfc_get_logical_type (gfc_default_logical_kind ());
+
+ boolean_true_node = build_int_2 (1, 0);
+ TREE_TYPE (boolean_true_node) = boolean_type_node;
+ boolean_false_node = build_int_2 (0, 0);
+ TREE_TYPE (boolean_false_node) = boolean_type_node;
+}
+
+/* Get a type node for an integer kind */
+tree
+gfc_get_int_type (int kind)
+{
+ switch (kind)
+ {
+ case 1:
+ return (gfc_int1_type_node);
+ case 2:
+ return (gfc_int2_type_node);
+ case 4:
+ return (gfc_int4_type_node);
+ case 8:
+ return (gfc_int8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ case 16:
+ return (95 _int16_type_node);
+#endif
+ default:
+ fatal_error ("integer kind=%d not available", kind);
+ }
+}
+
+/* Get a type node for a real kind */
+tree
+gfc_get_real_type (int kind)
+{
+ switch (kind)
+ {
+ case 4:
+ return (gfc_real4_type_node);
+ case 8:
+ return (gfc_real8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ case 16:
+ return (gfc_real16_type_node);
+#endif
+ default:
+ fatal_error ("real kind=%d not available", kind);
+ }
+}
+
+/* Get a type node for a complex kind */
+tree
+gfc_get_complex_type (int kind)
+{
+ switch (kind)
+ {
+ case 4:
+ return (gfc_complex4_type_node);
+ case 8:
+ return (gfc_complex8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ case 16:
+ return (gfc_complex16_type_node);
+#endif
+ default:
+ fatal_error ("complex kind=%d not available", kind);
+ }
+}
+
+/* Get a type node for a logical kind */
+tree
+gfc_get_logical_type (int kind)
+{
+ switch (kind)
+ {
+ case 1:
+ return (gfc_logical1_type_node);
+ case 2:
+ return (gfc_logical2_type_node);
+ case 4:
+ return (gfc_logical4_type_node);
+ case 8:
+ return (gfc_logical8_type_node);
+#if (GFC_USE_TYPES16 && (HOST_BITS_PER_WIDE_INT >= 64))
+ case 16:
+ return (gfc_logical16_type_node);
+#endif
+ default:
+ fatal_error ("logical kind=%d not available", kind);
+ }
+}
+
+/* Get a type node for a character kind. */
+tree
+gfc_get_character_type (int kind, gfc_charlen * cl)
+{
+ tree base;
+ tree type;
+ tree len;
+ tree bounds;
+
+ switch (kind)
+ {
+ case 1:
+ base = gfc_character1_type_node;
+ break;
+
+ default:
+ fatal_error ("character kind=%d not available", kind);
+ }
+
+ len = (cl == 0) ? NULL_TREE : cl->backend_decl;
+
+ bounds = build_range_type (gfc_array_index_type, integer_one_node, len);
+ type = build_array_type (base, bounds);
+ TYPE_STRING_FLAG (type) = 1;
+
+ return type;
+}
+
+/* Covert a basic type. This will be an array for character types. */
+tree
+gfc_typenode_for_spec (gfc_typespec * spec)
+{
+ tree basetype;
+
+ switch (spec->type)
+ {
+ case BT_UNKNOWN:
+ abort ();
+ break;
+
+ case BT_INTEGER:
+ basetype = gfc_get_int_type (spec->kind);
+ break;
+
+ case BT_REAL:
+ basetype = gfc_get_real_type (spec->kind);
+ break;
+
+ case BT_COMPLEX:
+ basetype = gfc_get_complex_type (spec->kind);
+ break;
+
+ case BT_LOGICAL:
+ basetype = gfc_get_logical_type (spec->kind);
+ break;
+
+ case BT_CHARACTER:
+ basetype = gfc_get_character_type (spec->kind, spec->cl);
+ break;
+
+ case BT_DERIVED:
+ basetype = gfc_get_derived_type (spec->derived);
+ break;
+
+ default:
+ abort ();
+ break;
+ }
+ return basetype;
+}
+
+/* Build an INT_CST for constant expressions, otherwise return NULL_TREE. */
+static tree
+gfc_conv_array_bound (gfc_expr * expr)
+{
+ /* If expr is an integer constant, return that. */
+ if (expr != NULL && expr->expr_type == EXPR_CONSTANT)
+ return gfc_conv_mpz_to_tree (expr->value.integer, gfc_index_integer_kind);
+
+ /* Otherwise return NULL. */
+ return NULL_TREE;
+}
+
+tree
+gfc_get_element_type (tree type)
+{
+ tree element;
+
+ if (GFC_ARRAY_TYPE_P (type))
+ {
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TREE_TYPE (type);
+ assert (TREE_CODE (type) == ARRAY_TYPE);
+ element = TREE_TYPE (type);
+ }
+ else
+ {
+ assert (GFC_DESCRIPTOR_TYPE_P (type));
+ element = TREE_TYPE (TYPE_FIELDS (type));
+
+ assert (TREE_CODE (element) == POINTER_TYPE);
+ element = TREE_TYPE (element);
+
+ assert (TREE_CODE (element) == ARRAY_TYPE);
+ element = TREE_TYPE (element);
+ }
+
+ return element;
+}
+
+/* Build an array. This function is called from gfc_sym_type().
+ Actualy returns array descriptor type.
+
+ Format of array descriptors is as follows:
+
+ struct gfc_array_descriptor
+ {
+ array *data
+ index offset;
+ index dtype;
+ struct descriptor_dimension dimension[N_DIM];
+ }
+
+ struct descriptor_dimension
+ {
+ index stride;
+ index lbound;
+ index ubound;
+ }
+
+ Translation code should use gfc_conv_descriptor_* rather than accessing
+ the descriptor directly. Any changes to the array descriptor type will
+ require changes in gfc_conv_descriptor_* and gfc_build_array_initializer.
+
+ This is represented internaly as a RECORD_TYPE. The index nodes are
+ gfc_array_index_type and the data node is a pointer to the data. See below
+ for the handling of character types.
+
+ The dtype member is formatted as follows:
+ rank = dtype & GFC_DTYPE_RANK_MASK // 3 bits
+ type = (dtype & GFC_DTYPE_TYPE_MASK) >> GFC_DTYPE_TYPE_SHIFT // 3 bits
+ size = dtype >> GFC_DTYPE_SIZE_SHIFT
+
+ I originaly used nested ARRAY_TYPE nodes to represent arrays, but this
+ generated poor code for assumed/deferred size arrays. These require
+ use of PLACEHOLDER_EXPR/WITH_RECORD_EXPR, which isn't part of GIMPLE
+ grammar. Also, there is no way to explicitly set the array stride, so
+ all data must be packed(1). I've tried to mark all the functions which
+ would require modification with a GCC ARRAYS comment.
+
+ The data component points to the first element in the array.
+ The offset field is the position of the origin of the array
+ (ie element (0, 0 ...)). This may be outsite the bounds of the array.
+
+ An element is accessed by
+ data[offset + index0*stride0 + index1*stride1 + index2*stride2]
+ This gives good performance as it computation does not involve the
+ bounds of the array. For packed arrays, this is optimized further by
+ substituting the known strides.
+
+ This system has one problem: all array bounds must be withing 2^31 elements
+ of the origin (2^63 on 64-bit machines). For example
+ integer, dimension (80000:90000, 80000:90000, 2) :: array
+ may not work properly on 32-bit machines because 80000*80000 > 2^31, so
+ the calculation for stride02 would overflow. This may still work, but
+ I haven't checked, and it relies on the overflow doing the right thing.
+
+ The way to fix this problem is to access alements as follows:
+ data[(index0-lbound0)*stride0 + (index1-lbound1)*stride1]
+ Obviously this is much slower. I will make this a compile time option,
+ something like -fsmall-array-offsets. Mixing code compiled with and without
+ this switch will work.
+
+ (1) This can be worked around by modifying the upper bound of the previous
+ dimension. This requires extra fields in the descriptor (both real_ubound
+ and fake_ubound). In tree.def there is mention of TYPE_SEP, which
+ may allow us to do this. However I can't find mention of this anywhere
+ else.
+ */
+
+
+/* Returns true if the array sym does not require a descriptor. */
+
+int
+gfc_is_nodesc_array (gfc_symbol * sym)
+{
+ assert (sym->attr.dimension);
+
+ /* We only want local arrays. */
+ if (sym->attr.pointer || sym->attr.allocatable)
+ return 0;
+
+ if (sym->attr.dummy)
+ {
+ if (sym->as->type != AS_ASSUMED_SHAPE)
+ return 1;
+ else
+ return 0;
+ }
+
+ if (sym->attr.result || sym->attr.function)
+ return 0;
+
+ if (sym->attr.pointer || sym->attr.allocatable)
+ return 0;
+
+ assert (sym->as->type == AS_EXPLICIT);
+
+ return 1;
+}
+
+static tree
+gfc_build_array_type (tree type, gfc_array_spec * as)
+{
+ tree lbound[GFC_MAX_DIMENSIONS];
+ tree ubound[GFC_MAX_DIMENSIONS];
+ int n;
+
+ for (n = 0; n < as->rank; n++)
+ {
+ /* Create expressions for the known bounds of the array. */
+ if (as->type == AS_ASSUMED_SHAPE && as->lower[n] == NULL)
+ lbound[n] = integer_one_node;
+ else
+ lbound[n] = gfc_conv_array_bound (as->lower[n]);
+ ubound[n] = gfc_conv_array_bound (as->upper[n]);
+ }
+
+ return gfc_get_array_type_bounds (type, as->rank, lbound, ubound, 0);
+}
+
+/* Returns the struct descriptor_dimension type. */
+static tree
+gfc_get_desc_dim_type (void)
+{
+ tree type;
+ tree decl;
+ tree fieldlist;
+
+ if (gfc_desc_dim_type)
+ return gfc_desc_dim_type;
+
+ /* Build the type node. */
+ type = make_node (RECORD_TYPE);
+
+ TYPE_NAME (type) = get_identifier ("descriptor_dimension");
+ TYPE_PACKED (type) = 1;
+
+ /* Consists of the stride, lbound and ubound members. */
+ decl = build_decl (FIELD_DECL,
+ get_identifier ("stride"), gfc_array_index_type);
+ DECL_CONTEXT (decl) = type;
+ fieldlist = decl;
+
+ decl = build_decl (FIELD_DECL,
+ get_identifier ("lbound"), gfc_array_index_type);
+ DECL_CONTEXT (decl) = type;
+ fieldlist = chainon (fieldlist, decl);
+
+ decl = build_decl (FIELD_DECL,
+ get_identifier ("ubound"), gfc_array_index_type);
+ DECL_CONTEXT (decl) = type;
+ fieldlist = chainon (fieldlist, decl);
+
+ /* Finish off the type. */
+ TYPE_FIELDS (type) = fieldlist;
+
+ gfc_finish_type (type);
+
+ gfc_desc_dim_type = type;
+ return type;
+}
+
+static tree
+gfc_get_dtype (tree type, int rank)
+{
+ tree size;
+ int n;
+ HOST_WIDE_INT i;
+ tree tmp;
+ tree dtype;
+
+ if (GFC_DESCRIPTOR_TYPE_P (type) || GFC_ARRAY_TYPE_P (type))
+ return (GFC_TYPE_ARRAY_DTYPE (type));
+
+ /* TODO: Correctly identify LOGICAL types. */
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE:
+ n = GFC_DTYPE_INTEGER;
+ break;
+
+ case BOOLEAN_TYPE:
+ n = GFC_DTYPE_LOGICAL;
+ break;
+
+ case REAL_TYPE:
+ n = GFC_DTYPE_REAL;
+ break;
+
+ case COMPLEX_TYPE:
+ n = GFC_DTYPE_COMPLEX;
+ break;
+
+ /* Arrays have already been dealt with. */
+ case RECORD_TYPE:
+ n = GFC_DTYPE_DERIVED;
+ break;
+
+ case ARRAY_TYPE:
+ n = GFC_DTYPE_CHARACTER;
+ break;
+
+ default:
+ abort ();
+ }
+
+ assert (rank <= GFC_DTYPE_RANK_MASK);
+ size = TYPE_SIZE_UNIT (type);
+
+ i = rank | (n << GFC_DTYPE_TYPE_SHIFT);
+ if (size && INTEGER_CST_P (size))
+ {
+ if (tree_int_cst_lt (gfc_max_array_element_size, size))
+ internal_error ("Array element size too big");
+
+ i += TREE_INT_CST_LOW (size) << GFC_DTYPE_SIZE_SHIFT;
+ }
+ dtype = build_int_2 (i, 0);
+ TREE_TYPE (dtype) = gfc_array_index_type;
+
+ if (size && !INTEGER_CST_P (size))
+ {
+ tmp = build_int_2 (GFC_DTYPE_SIZE_SHIFT, 0);
+ TREE_TYPE (tmp) = gfc_array_index_type;
+ tmp = fold (build (LSHIFT_EXPR, gfc_array_index_type, size, tmp));
+ dtype = fold (build (PLUS_EXPR, gfc_array_index_type, tmp, dtype));
+ }
+ /* If we don't know the size we leave it as zero. This should never happen
+ for anything that is actually used. */
+ /* TODO: Check this is actually true, particularly when repacking
+ assumed size parameters. */
+
+ return dtype;
+}
+
+
+/* Build an array type for use without a descriptor. Valid values of packed
+ are 0=no, 1=partial, 2=full, 3=static. */
+
+tree
+gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, int packed)
+{
+ tree range;
+ tree type;
+ tree tmp;
+ int n;
+ int known_stride;
+ int known_offset;
+ mpz_t offset;
+ mpz_t stride;
+ mpz_t delta;
+ gfc_expr *expr;
+
+ mpz_init_set_ui (offset, 0);
+ mpz_init_set_ui (stride, 1);
+ mpz_init (delta);
+
+ /* We don't use build_array_type because this does not include include
+ lang-specific information (ie. the bounds of the array) when checking
+ for duplicates. */
+ type = make_node (ARRAY_TYPE);
+
+ GFC_ARRAY_TYPE_P (type) = 1;
+ TYPE_LANG_SPECIFIC (type) = (struct lang_type *)
+ ggc_alloc_cleared (sizeof (struct lang_type));
+
+ known_stride = (packed != 0);
+ known_offset = 1;
+ for (n = 0; n < as->rank; n++)
+ {
+ /* Fill in the stride and bound components of the type. */
+ if (known_stride)
+ tmp = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
+ else
+ tmp = NULL_TREE;
+ GFC_TYPE_ARRAY_STRIDE (type, n) = tmp;
+
+ expr = as->lower[n];
+ if (expr->expr_type == EXPR_CONSTANT)
+ {
+ tmp = gfc_conv_mpz_to_tree (expr->value.integer,
+ gfc_index_integer_kind);
+ }
+ else
+ {
+ known_stride = 0;
+ tmp = NULL_TREE;
+ }
+ GFC_TYPE_ARRAY_LBOUND (type, n) = tmp;
+
+ if (known_stride)
+ {
+ /* Calculate the offset. */
+ mpz_mul (delta, stride, as->lower[n]->value.integer);
+ mpz_sub (offset, offset, delta);
+ }
+ else
+ known_offset = 0;
+
+ expr = as->upper[n];
+ if (expr && expr->expr_type == EXPR_CONSTANT)
+ {
+ tmp = gfc_conv_mpz_to_tree (expr->value.integer,
+ gfc_index_integer_kind);
+ }
+ else
+ {
+ tmp = NULL_TREE;
+ known_stride = 0;
+ }
+ GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;
+
+ if (known_stride)
+ {
+ /* Calculate the stride. */
+ mpz_sub (delta, as->upper[n]->value.integer,
+ as->lower[n]->value.integer);
+ mpz_add_ui (delta, delta, 1);
+ mpz_mul (stride, stride, delta);
+ }
+
+ /* Only the first stride is known for partial packed arrays. */
+ if (packed < 2)
+ known_stride = 0;
+ }
+
+ if (known_offset)
+ {
+ GFC_TYPE_ARRAY_OFFSET (type) =
+ gfc_conv_mpz_to_tree (offset, gfc_index_integer_kind);
+ }
+ else
+ GFC_TYPE_ARRAY_OFFSET (type) = NULL_TREE;
+
+ if (known_stride)
+ {
+ GFC_TYPE_ARRAY_SIZE (type) =
+ gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
+ }
+ else
+ GFC_TYPE_ARRAY_SIZE (type) = NULL_TREE;
+
+ GFC_TYPE_ARRAY_DTYPE (type) = gfc_get_dtype (etype, as->rank);
+ GFC_TYPE_ARRAY_RANK (type) = as->rank;
+ range = build_range_type (gfc_array_index_type, integer_zero_node,
+ NULL_TREE);
+ /* TODO: use main type if it is unbounded. */
+ GFC_TYPE_ARRAY_DATAPTR_TYPE (type) =
+ build_pointer_type (build_array_type (etype, range));
+
+ if (known_stride)
+ {
+ mpz_sub_ui (stride, stride, 1);
+ range = gfc_conv_mpz_to_tree (stride, gfc_index_integer_kind);
+ }
+ else
+ range = NULL_TREE;
+
+ range = build_range_type (gfc_array_index_type, integer_zero_node, range);
+ TYPE_DOMAIN (type) = range;
+
+ build_pointer_type (etype);
+ TREE_TYPE (type) = etype;
+
+ layout_type (type);
+
+ mpz_clear (offset);
+ mpz_clear (stride);
+ mpz_clear (delta);
+
+ if (packed < 3 || !known_stride)
+ {
+ type = build_pointer_type (type);
+ GFC_ARRAY_TYPE_P (type) = 1;
+ TYPE_LANG_SPECIFIC (type) = TYPE_LANG_SPECIFIC (TREE_TYPE (type));
+ }
+ return type;
+}
+
+
+/* Build an array (descriptor) type with given bounds. */
+
+tree
+gfc_get_array_type_bounds (tree etype, int dimen, tree * lbound,
+ tree * ubound, int packed)
+{
+ tree fat_type, fat_pointer_type;
+ tree fieldlist;
+ tree arraytype;
+ tree decl;
+ int n;
+ char name[8 + GFC_RANK_DIGITS + GFC_MAX_SYMBOL_LEN];
+ const char *typename;
+ tree lower;
+ tree upper;
+ tree stride;
+ tree tmp;
+
+ /* Build the type node. */
+ fat_type = make_node (RECORD_TYPE);
+ GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
+ TYPE_LANG_SPECIFIC (fat_type) = (struct lang_type *)
+ ggc_alloc_cleared (sizeof (struct lang_type));
+ GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
+ GFC_TYPE_ARRAY_DTYPE (fat_type) = gfc_get_dtype (etype, dimen);
+
+ tmp = TYPE_NAME (etype);
+ if (tmp && TREE_CODE (tmp) == TYPE_DECL)
+ tmp = DECL_NAME (tmp);
+ if (tmp)
+ typename = IDENTIFIER_POINTER (tmp);
+ else
+ typename = "unknown";
+
+ sprintf (name, "array" GFC_RANK_PRINTF_FORMAT "_%.*s", dimen,
+ GFC_MAX_SYMBOL_LEN, typename);
+ TYPE_NAME (fat_type) = get_identifier (name);
+ TYPE_PACKED (fat_type) = 0;
+
+ fat_pointer_type = build_pointer_type (fat_type);
+
+ /* Build an array descriptor record type. */
+ if (packed != 0)
+ stride = integer_one_node;
+ else
+ stride = NULL_TREE;
+
+ for (n = 0; n < dimen; n++)
+ {
+ GFC_TYPE_ARRAY_STRIDE (fat_type, n) = stride;
+
+ if (lbound)
+ lower = lbound[n];
+ else
+ lower = NULL_TREE;
+
+ if (lower != NULL_TREE)
+ {
+ if (INTEGER_CST_P (lower))
+ GFC_TYPE_ARRAY_LBOUND (fat_type, n) = lower;
+ else
+ lower = NULL_TREE;
+ }
+
+ upper = ubound[n];
+ if (upper != NULL_TREE)
+ {
+ if (INTEGER_CST_P (upper))
+ GFC_TYPE_ARRAY_UBOUND (fat_type, n) = upper;
+ else
+ upper = NULL_TREE;
+ }
+
+ if (upper != NULL_TREE && lower != NULL_TREE && stride != NULL_TREE)
+ {
+ tmp = fold (build (MINUS_EXPR, gfc_array_index_type, upper, lower));
+ tmp = fold (build (PLUS_EXPR, gfc_array_index_type, tmp,
+ integer_one_node));
+ stride =
+ fold (build (MULT_EXPR, gfc_array_index_type, tmp, stride));
+ /* Check the folding worked. */
+ assert (INTEGER_CST_P (stride));
+ }
+ else
+ stride = NULL_TREE;
+ }
+ GFC_TYPE_ARRAY_SIZE (fat_type) = stride;
+ /* TODO: known offsets for descriptors. */
+ GFC_TYPE_ARRAY_OFFSET (fat_type) = NULL_TREE;
+
+ /* We define data as an unknown size array. Much better than doing
+ pointer arithmetic. */
+ arraytype =
+ build_array_type (etype,
+ build_range_type (gfc_array_index_type,
+ integer_zero_node, NULL_TREE));
+ arraytype = build_pointer_type (arraytype);
+ GFC_TYPE_ARRAY_DATAPTR_TYPE (fat_type) = arraytype;
+
+ /* The pointer to the array data. */
+ decl = build_decl (FIELD_DECL, get_identifier ("data"), arraytype);
+
+ DECL_CONTEXT (decl) = fat_type;
+ /* Add the data member as the first element of the descriptor. */
+ fieldlist = decl;
+
+ /* Add the base component. */
+ decl = build_decl (FIELD_DECL, get_identifier ("offset"),
+ gfc_array_index_type);
+ DECL_CONTEXT (decl) = fat_type;
+ fieldlist = chainon (fieldlist, decl);
+
+ /* Add the dtype component. */
+ decl = build_decl (FIELD_DECL, get_identifier ("dtype"),
+ gfc_array_index_type);
+ DECL_CONTEXT (decl) = fat_type;
+ fieldlist = chainon (fieldlist, decl);
+
+ /* Build the array type for the stride and bound components. */
+ arraytype =
+ build_array_type (gfc_get_desc_dim_type (),
+ build_range_type (gfc_array_index_type,
+ integer_zero_node,
+ gfc_rank_cst[dimen - 1]));
+
+ decl = build_decl (FIELD_DECL, get_identifier ("dim"), arraytype);
+ DECL_CONTEXT (decl) = fat_type;
+ DECL_INITIAL (decl) = NULL_TREE;
+ fieldlist = chainon (fieldlist, decl);
+
+ /* Finish off the type. */
+ TYPE_FIELDS (fat_type) = fieldlist;
+
+ gfc_finish_type (fat_type);
+
+ return fat_type;
+}
+
+/* Build a pointer type. This function is called from gfc_sym_type(). */
+static tree
+gfc_build_pointer_type (gfc_symbol * sym, tree type)
+{
+ /* Array pointer types aren't actualy pointers. */
+ if (sym->attr.dimension)
+ return type;
+ else
+ return build_pointer_type (type);
+}
+
+/* Return the type for a symbol. Special handling is required for character
+ types to get the correct level of indirection.
+ For functions return the return type.
+ For subroutines return void_type_node.
+ */
+tree
+gfc_sym_type (gfc_symbol * sym)
+{
+ tree type;
+ int byref;
+
+ if (sym->attr.flavor == FL_PROCEDURE && !sym->attr.function)
+ return void_type_node;
+
+ if (sym->backend_decl)
+ {
+ if (sym->attr.function)
+ return TREE_TYPE (TREE_TYPE (sym->backend_decl));
+ else
+ return TREE_TYPE (sym->backend_decl);
+ }
+
+ /* The frontend doesn't set all the attributes for a function with an
+ explicit result value, so we use that instead when present. */
+ if (sym->attr.function && sym->result)
+ sym = sym->result;
+
+ type = gfc_typenode_for_spec (&sym->ts);
+
+ if (sym->attr.dummy && !sym->attr.function)
+ byref = 1;
+ else
+ byref = 0;
+
+ if (sym->attr.dimension)
+ {
+ if (gfc_is_nodesc_array (sym))
+ {
+ /* If this is a character argument of unknown length, just use the
+ base type. */
+ if (sym->ts.type != BT_CHARACTER
+ || !(sym->attr.dummy || sym->attr.function || sym->attr.result)
+ || sym->ts.cl->backend_decl)
+ {
+ type = gfc_get_nodesc_array_type (type, sym->as,
+ byref ? 2 : 3);
+ byref = 0;
+ }
+ }
+ else
+ type = gfc_build_array_type (type, sym->as);
+ }
+ else
+ {
+ if (sym->attr.allocatable || sym->attr.pointer)
+ type = gfc_build_pointer_type (sym, type);
+ }
+
+ /* We currently pass all parameters by reference.
+ See f95_get_function_decl. For dummy function parameters return the
+ function type. */
+ if (byref)
+ type = build_reference_type (type);
+
+ return (type);
+}
+
+/* Layout and output debug info for a record type. */
+void
+gfc_finish_type (tree type)
+{
+ tree decl;
+
+ decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ TYPE_STUB_DECL (type) = decl;
+ layout_type (type);
+ rest_of_type_compilation (type, 1);
+ rest_of_decl_compilation (decl, NULL, 1, 0);
+}
+
+/* Add a field of given NAME and TYPE to the context of a UNION_TYPE
+ or RECORD_TYPE pointed to by STYPE. The new field is chained
+ to the fieldlist pointed to by FIELDLIST.
+
+ Returns a pointer to the new field. */
+tree
+gfc_add_field_to_struct (tree *fieldlist, tree context,
+ tree name, tree type)
+{
+ tree decl;
+
+ decl = build_decl (FIELD_DECL, name, type);
+
+ DECL_CONTEXT (decl) = context;
+ DECL_INITIAL (decl) = 0;
+ DECL_ALIGN (decl) = 0;
+ DECL_USER_ALIGN (decl) = 0;
+ TREE_CHAIN (decl) = NULL_TREE;
+ *fieldlist = chainon (*fieldlist, decl);
+
+ return decl;
+}
+
+
+/* Build a tree node for a derived type. */
+static tree
+gfc_get_derived_type (gfc_symbol * derived)
+{
+ tree typenode, field, field_type, fieldlist;
+ gfc_component *c;
+
+ assert (derived && derived->attr.flavor == FL_DERIVED);
+
+ /* derived->backend_decl != 0 means we saw it before, but its
+ component's backend_decl may have not been built. */
+ if (derived->backend_decl)
+ {
+ /* Its component's backend_decl has been built. */
+ if (TYPE_FIELDS (derived->backend_decl))
+ return derived->backend_decl;
+ else
+ typenode = derived->backend_decl;
+ }
+ else
+ {
+ /* We see this derived type first time, so build the type node. */
+ typenode = make_node (RECORD_TYPE);
+ TYPE_NAME (typenode) = get_identifier (derived->name);
+ TYPE_PACKED (typenode) = gfc_option.flag_pack_derived;
+ derived->backend_decl = typenode;
+ }
+
+ /* Build the type member list. Install the newly created RECORD_TYPE
+ node as DECL_CONTEXT of each FIELD_DECL. */
+ fieldlist = NULL_TREE;
+ for (c = derived->components; c; c = c->next)
+ {
+ if (c->ts.type == BT_DERIVED && c->pointer)
+ {
+ if (c->ts.derived->backend_decl)
+ field_type = c->ts.derived->backend_decl;
+ else
+ {
+ /* Build the type node. */
+ field_type = make_node (RECORD_TYPE);
+ TYPE_NAME (field_type) = get_identifier (c->ts.derived->name);
+ TYPE_PACKED (field_type) = gfc_option.flag_pack_derived;
+ c->ts.derived->backend_decl = field_type;
+ }
+ }
+ else
+ {
+ if (c->ts.type == BT_CHARACTER)
+ {
+ /* Evaluate the string length. */
+ gfc_conv_const_charlen (c->ts.cl);
+ assert (c->ts.cl->backend_decl);
+ }
+
+ field_type = gfc_typenode_for_spec (&c->ts);
+ }
+
+ /* This returns an array descriptor type. Initialisation may be
+ required. */
+ if (c->dimension)
+ {
+ if (c->pointer)
+ {
+ /* Pointers to arrays aren't actualy pointer types. The
+ descriptors are seperate, but the data is common. */
+ field_type = gfc_build_array_type (field_type, c->as);
+ }
+ else
+ field_type = gfc_get_nodesc_array_type (field_type, c->as, 3);
+ }
+ else if (c->pointer)
+ field_type = build_pointer_type (field_type);
+
+ field = gfc_add_field_to_struct (&fieldlist, typenode,
+ get_identifier (c->name),
+ field_type);
+
+ DECL_PACKED (field) |= TYPE_PACKED (typenode);
+
+ assert (!c->backend_decl);
+ c->backend_decl = field;
+ }
+
+ /* Now we have the final fieldlist. Record it, then lay out the
+ derived type, including the fields. */
+ TYPE_FIELDS (typenode) = fieldlist;
+
+ gfc_finish_type (typenode);
+
+ derived->backend_decl = typenode;
+
+ return typenode;
+}
+
+int
+gfc_return_by_reference (gfc_symbol * sym)
+{
+ if (!sym->attr.function)
+ return 0;
+
+ assert (sym->attr.function);
+
+ if (sym->result)
+ sym = sym->result;
+
+ if (sym->attr.dimension)
+ return 1;
+
+ if (sym->ts.type == BT_CHARACTER)
+ return 1;
+
+ if (sym->ts.type == BT_DERIVED)
+ gfc_todo_error ("Returning derived types");
+ /* Possibly return derived types by reference. */
+ return 0;
+}
+
+tree
+gfc_get_function_type (gfc_symbol * sym)
+{
+ tree type;
+ tree typelist;
+ gfc_formal_arglist *f;
+ gfc_symbol *arg;
+ int nstr;
+ int alternate_return;
+
+ /* Make sure this symbol is a function or a subroutine. */
+ assert (sym->attr.flavor == FL_PROCEDURE);
+
+ if (sym->backend_decl)
+ return TREE_TYPE (sym->backend_decl);
+
+ nstr = 0;
+ alternate_return = 0;
+ typelist = NULL_TREE;
+ /* Some functions we use an extra parameter for the return value. */
+ if (gfc_return_by_reference (sym))
+ {
+ if (sym->result)
+ arg = sym->result;
+ else
+ arg = sym;
+
+ if (arg->ts.type == BT_CHARACTER)
+ gfc_conv_const_charlen (arg->ts.cl);
+
+ type = gfc_sym_type (arg);
+ if (arg->ts.type == BT_DERIVED
+ || arg->attr.dimension
+ || arg->ts.type == BT_CHARACTER)
+ type = build_reference_type (type);
+
+ typelist = gfc_chainon_list (typelist, type);
+ if (arg->ts.type == BT_CHARACTER)
+ typelist = gfc_chainon_list (typelist, gfc_strlen_type_node);
+ }
+
+ /* Build the argument types for the function */
+ for (f = sym->formal; f; f = f->next)
+ {
+ arg = f->sym;
+ if (arg)
+ {
+ /* Evaluate constant character lengths here so that they can be
+ included in the type. */
+ if (arg->ts.type == BT_CHARACTER)
+ gfc_conv_const_charlen (arg->ts.cl);
+
+ if (arg->attr.flavor == FL_PROCEDURE)
+ {
+ type = gfc_get_function_type (arg);
+ type = build_pointer_type (type);
+ }
+ else
+ type = gfc_sym_type (arg);
+
+ /* Parameter Passing Convention
+
+ We currently pass all parameters by reference.
+ Parameters with INTENT(IN) could be passed by value.
+ The problem arises if a function is called via an implicit
+ prototype. In this situation the INTENT is not known.
+ For this reason all parameters to global functions must be
+ passed by reference. Passing by value would potentialy
+ generate bad code. Worse there would be no way of telling that
+ this code wad bad, except that it would give incorrect results.
+
+ Contained procedures could pass by value as these are never
+ used without an explicit interface, and connot be passed as
+ actual parameters for a dummy procedure.
+ */
+ if (arg->ts.type == BT_CHARACTER)
+ nstr++;
+ typelist = gfc_chainon_list (typelist, type);
+ }
+ else
+ {
+ if (sym->attr.subroutine)
+ alternate_return = 1;
+ }
+ }
+
+ /* Add hidden string length parameters. */
+ while (nstr--)
+ typelist = gfc_chainon_list (typelist, gfc_strlen_type_node);
+
+ typelist = gfc_chainon_list (typelist, void_type_node);
+
+ if (alternate_return)
+ type = integer_type_node;
+ else if (!sym->attr.function || gfc_return_by_reference (sym))
+ type = void_type_node;
+ else
+ type = gfc_sym_type (sym);
+
+ type = build_function_type (type, typelist);
+
+ return type;
+}
+
+/* Routines for getting integer type nodes */
+
+
+/* Return an integer type with BITS bits of precision,
+ that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
+
+tree
+gfc_type_for_size (unsigned bits, int unsignedp)
+{
+ if (bits == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+
+ if (bits == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+
+ if (bits == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+
+ if (bits == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+ if (bits == TYPE_PRECISION (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+/*TODO: We currently don't initialise this...
+ if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
+ return (unsignedp ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node);*/
+
+ if (bits <= TYPE_PRECISION (intQI_type_node))
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (bits <= TYPE_PRECISION (intHI_type_node))
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (bits <= TYPE_PRECISION (intSI_type_node))
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (bits <= TYPE_PRECISION (intDI_type_node))
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+
+ return 0;
+}
+
+/* Return a data type that has machine mode MODE.
+ If the mode is an integer,
+ then UNSIGNEDP selects between signed and unsigned types. */
+
+tree
+gfc_type_for_mode (enum machine_mode mode, int unsignedp)
+{
+ if (mode == TYPE_MODE (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+
+ if (mode == TYPE_MODE (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+
+ if (mode == TYPE_MODE (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+
+ if (mode == TYPE_MODE (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+
+ if (mode == TYPE_MODE (long_long_integer_type_node))
+ return unsignedp ? long_long_unsigned_type_node :
+ long_long_integer_type_node;
+
+/*TODO: see above
+ if (mode == TYPE_MODE (widest_integer_literal_type_node))
+ return unsignedp ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node;
+*/
+
+ if (mode == QImode)
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ if (mode == HImode)
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+
+ if (mode == SImode)
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+
+ if (mode == DImode)
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (mode == TYPE_MODE (intTI_type_node))
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+
+ if (mode == TYPE_MODE (float_type_node))
+ return float_type_node;
+
+ if (mode == TYPE_MODE (double_type_node))
+ return double_type_node;
+
+ if (mode == TYPE_MODE (long_double_type_node))
+ return long_double_type_node;
+
+ if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
+ return build_pointer_type (char_type_node);
+
+ if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
+ return build_pointer_type (integer_type_node);
+
+#ifdef VECTOR_MODE_SUPPORTED_P
+ if (VECTOR_MODE_SUPPORTED_P (mode))
+ {
+ switch (mode)
+ {
+ case V16QImode:
+ return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
+ case V8HImode:
+ return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
+ case V4SImode:
+ return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
+ case V2DImode:
+ return unsignedp ? unsigned_V2DI_type_node : V2DI_type_node;
+ case V2SImode:
+ return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+ case V4HImode:
+ return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
+ case V8QImode:
+ return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+ case V16SFmode:
+ return V16SF_type_node;
+ case V4SFmode:
+ return V4SF_type_node;
+ case V2SFmode:
+ return V2SF_type_node;
+ case V2DFmode:
+ return V2DF_type_node;
+ default:
+ break;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+/* Return an unsigned type the same as TYPE in other respects. */
+tree
+gfc_unsigned_type (tree type)
+{
+ tree type1 = TYPE_MAIN_VARIANT (type);
+ if (type1 == signed_char_type_node || type1 == char_type_node)
+ return unsigned_char_type_node;
+ if (type1 == integer_type_node)
+ return unsigned_type_node;
+ if (type1 == short_integer_type_node)
+ return short_unsigned_type_node;
+ if (type1 == long_integer_type_node)
+ return long_unsigned_type_node;
+ if (type1 == long_long_integer_type_node)
+ return long_long_unsigned_type_node;
+/*TODO :see others
+ if (type1 == widest_integer_literal_type_node)
+ return widest_unsigned_literal_type_node;
+*/
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (type1 == intTI_type_node)
+ return unsigned_intTI_type_node;
+#endif
+ if (type1 == intDI_type_node)
+ return unsigned_intDI_type_node;
+ if (type1 == intSI_type_node)
+ return unsigned_intSI_type_node;
+ if (type1 == intHI_type_node)
+ return unsigned_intHI_type_node;
+ if (type1 == intQI_type_node)
+ return unsigned_intQI_type_node;
+
+ return gfc_signed_or_unsigned_type (1, type);
+}
+
+/* Return a signed type the same as TYPE in other respects. */
+
+tree
+gfc_signed_type (tree type)
+{
+ tree type1 = TYPE_MAIN_VARIANT (type);
+ if (type1 == unsigned_char_type_node || type1 == char_type_node)
+ return signed_char_type_node;
+ if (type1 == unsigned_type_node)
+ return integer_type_node;
+ if (type1 == short_unsigned_type_node)
+ return short_integer_type_node;
+ if (type1 == long_unsigned_type_node)
+ return long_integer_type_node;
+ if (type1 == long_long_unsigned_type_node)
+ return long_long_integer_type_node;
+/*TODO: see others
+ if (type1 == widest_unsigned_literal_type_node)
+ return widest_integer_literal_type_node;
+*/
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (type1 == unsigned_intTI_type_node)
+ return intTI_type_node;
+#endif
+ if (type1 == unsigned_intDI_type_node)
+ return intDI_type_node;
+ if (type1 == unsigned_intSI_type_node)
+ return intSI_type_node;
+ if (type1 == unsigned_intHI_type_node)
+ return intHI_type_node;
+ if (type1 == unsigned_intQI_type_node)
+ return intQI_type_node;
+
+ return gfc_signed_or_unsigned_type (0, type);
+}
+
+/* Return a type the same as TYPE except unsigned or
+ signed according to UNSIGNEDP. */
+
+tree
+gfc_signed_or_unsigned_type (int unsignedp, tree type)
+{
+ if (!INTEGRAL_TYPE_P (type) || TYPE_UNSIGNED (type) == unsignedp)
+ return type;
+
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node))
+ return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node))
+ return unsignedp ? unsigned_type_node : integer_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (short_integer_type_node))
+ return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (long_integer_type_node))
+ return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (long_long_integer_type_node))
+ return (unsignedp ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+/*TODO: see others
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (widest_integer_literal_type_node))
+ return (unsignedp ? widest_unsigned_literal_type_node
+ : widest_integer_literal_type_node);
+*/
+#if HOST_BITS_PER_WIDE_INT >= 64
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (intTI_type_node))
+ return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
+#endif
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (intDI_type_node))
+ return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (intSI_type_node))
+ return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (intHI_type_node))
+ return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
+ if (TYPE_PRECISION (type) == TYPE_PRECISION (intQI_type_node))
+ return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
+
+ return type;
+}
+
+#include "gt-fortran-trans-types.h"