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.c265
1 files changed, 219 insertions, 46 deletions
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 831c84fe28..fc5e486379 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1,5 +1,5 @@
/* Backend support for Fortran 95 basic types and derived types.
- Copyright (C) 2002-2016 Free Software Foundation, Inc.
+ Copyright (C) 2002-2017 Free Software Foundation, Inc.
Contributed by Paul Brook <paul@nowt.org>
and Steven Bosscher <s.bosscher@student.tudelft.nl>
@@ -62,8 +62,8 @@ tree pfunc_type_node;
tree gfc_charlen_type_node;
-tree float128_type_node = NULL_TREE;
-tree complex_float128_type_node = NULL_TREE;
+tree gfc_float128_type_node = NULL_TREE;
+tree gfc_complex_float128_type_node = NULL_TREE;
bool gfc_real16_is_float128 = false;
@@ -234,27 +234,42 @@ gfc_get_int_kind_from_width_isofortranenv (int size)
return -1;
}
-/* Get the kind number corresponding to a real of given storage size,
- following the required return values for ISO_FORTRAN_ENV REAL* constants:
- -2 is returned if we support a kind of larger size, -1 otherwise. */
+
+/* Get the kind number corresponding to a real of a given storage size.
+ If two real's have the same storage size, then choose the real with
+ the largest precision. If a kind type is unavailable and a real
+ exists with wider storage, then return -2; otherwise, return -1. */
+
int
gfc_get_real_kind_from_width_isofortranenv (int size)
{
- int i;
+ int digits, i, kind;
size /= 8;
+ kind = -1;
+ digits = 0;
+
/* Look for a kind with matching storage size. */
for (i = 0; gfc_real_kinds[i].kind != 0; i++)
if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) == size)
- return gfc_real_kinds[i].kind;
+ {
+ if (gfc_real_kinds[i].digits > digits)
+ {
+ digits = gfc_real_kinds[i].digits;
+ kind = gfc_real_kinds[i].kind;
+ }
+ }
+
+ if (kind != -1)
+ return kind;
/* Look for a kind with larger storage size. */
for (i = 0; gfc_real_kinds[i].kind != 0; i++)
if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) > size)
- return -2;
+ kind = -2;
- return -1;
+ return kind;
}
@@ -861,7 +876,7 @@ gfc_build_logical_type (gfc_logical_info *info)
void
gfc_init_types (void)
{
- char name_buf[18];
+ char name_buf[26];
int index;
tree type;
unsigned n;
@@ -901,7 +916,7 @@ gfc_init_types (void)
PUSH_TYPE (name_buf, type);
if (gfc_real_kinds[index].c_float128)
- float128_type_node = type;
+ gfc_float128_type_node = type;
type = gfc_build_complex_type (type);
gfc_complex_types[index] = type;
@@ -910,7 +925,7 @@ gfc_init_types (void)
PUSH_TYPE (name_buf, type);
if (gfc_real_kinds[index].c_float128)
- complex_float128_type_node = type;
+ gfc_complex_float128_type_node = type;
}
for (index = 0; gfc_character_kinds[index].kind != 0; ++index)
@@ -961,10 +976,6 @@ gfc_init_types (void)
wi::mask (n, UNSIGNED,
TYPE_PRECISION (size_type_node)));
- boolean_type_node = gfc_get_logical_type (gfc_default_logical_kind);
- boolean_true_node = build_int_cst (boolean_type_node, 1);
- boolean_false_node = build_int_cst (boolean_type_node, 0);
-
/* ??? Shouldn't this be based on gfc_index_integer_kind or so? */
gfc_charlen_int_kind = 4;
gfc_charlen_type_node = gfc_get_int_type (gfc_charlen_int_kind);
@@ -1051,10 +1062,10 @@ gfc_get_character_type (int kind, gfc_charlen * cl)
return gfc_get_character_type_len (kind, len);
}
-/* Covert a basic type. This will be an array for character types. */
+/* Convert a basic type. This will be an array for character types. */
tree
-gfc_typenode_for_spec (gfc_typespec * spec)
+gfc_typenode_for_spec (gfc_typespec * spec, int codim)
{
tree basetype;
@@ -1107,7 +1118,7 @@ gfc_typenode_for_spec (gfc_typespec * spec)
case BT_DERIVED:
case BT_CLASS:
- basetype = gfc_get_derived_type (spec->u.derived);
+ basetype = gfc_get_derived_type (spec->u.derived, codim);
if (spec->type == BT_CLASS)
GFC_CLASS_TYPE_P (basetype) = 1;
@@ -1311,7 +1322,7 @@ gfc_is_nodesc_array (gfc_symbol * sym)
static tree
gfc_build_array_type (tree type, gfc_array_spec * as,
enum gfc_array_kind akind, bool restricted,
- bool contiguous)
+ bool contiguous, int codim)
{
tree lbound[GFC_MAX_DIMENSIONS];
tree ubound[GFC_MAX_DIMENSIONS];
@@ -1319,10 +1330,10 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
/* Assumed-shape arrays do not have codimension information stored in the
descriptor. */
- corank = as->corank;
+ corank = MAX (as->corank, codim);
if (as->type == AS_ASSUMED_SHAPE ||
(as->type == AS_ASSUMED_RANK && akind == GFC_ARRAY_ALLOCATABLE))
- corank = 0;
+ corank = codim;
if (as->type == AS_ASSUMED_RANK)
for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
@@ -1360,8 +1371,8 @@ gfc_build_array_type (tree type, gfc_array_spec * as,
: GFC_ARRAY_ASSUMED_RANK;
return gfc_get_array_type_bounds (type, as->rank == -1
? GFC_MAX_DIMENSIONS : as->rank,
- corank, lbound,
- ubound, 0, akind, restricted);
+ corank, lbound, ubound, 0, akind,
+ restricted);
}
/* Returns the struct descriptor_dimension type. */
@@ -1723,8 +1734,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
/* Return or create the base type for an array descriptor. */
static tree
-gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
- enum gfc_array_kind akind)
+gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted)
{
tree fat_type, decl, arraytype, *chain = NULL;
char name[16 + 2*GFC_RANK_DIGITS + 1 + 1];
@@ -1786,8 +1796,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
TREE_NO_WARNING (decl) = 1;
}
- if (flag_coarray == GFC_FCOARRAY_LIB && codimen
- && akind == GFC_ARRAY_ALLOCATABLE)
+ if (flag_coarray == GFC_FCOARRAY_LIB && codimen)
{
decl = gfc_add_field_to_struct_1 (fat_type,
get_identifier ("token"),
@@ -1799,8 +1808,7 @@ gfc_get_array_descriptor_base (int dimen, int codimen, bool restricted,
gfc_finish_type (fat_type);
TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (fat_type)) = 1;
- if (flag_coarray == GFC_FCOARRAY_LIB && codimen
- && akind == GFC_ARRAY_ALLOCATABLE)
+ if (flag_coarray == GFC_FCOARRAY_LIB && codimen)
gfc_array_descriptor_base_caf[idx] = fat_type;
else
gfc_array_descriptor_base[idx] = fat_type;
@@ -1821,11 +1829,11 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
const char *type_name;
int n;
- base_type = gfc_get_array_descriptor_base (dimen, codimen, restricted, akind);
+ base_type = gfc_get_array_descriptor_base (dimen, codimen, restricted);
fat_type = build_distinct_type_copy (base_type);
/* Make sure that nontarget and target array type have the same canonical
type (and same stub decl for debug info). */
- base_type = gfc_get_array_descriptor_base (dimen, codimen, false, akind);
+ base_type = gfc_get_array_descriptor_base (dimen, codimen, false);
TYPE_CANONICAL (fat_type) = base_type;
TYPE_STUB_DECL (fat_type) = TYPE_STUB_DECL (base_type);
@@ -2161,7 +2169,7 @@ gfc_sym_type (gfc_symbol * sym)
|| !sym->ts.u.cl->backend_decl))))
type = gfc_character1_type_node;
else
- type = gfc_typenode_for_spec (&sym->ts);
+ type = gfc_typenode_for_spec (&sym->ts, sym->attr.codimension);
if (sym->attr.dummy && !sym->attr.function && !sym->attr.value)
byref = 1;
@@ -2199,7 +2207,7 @@ gfc_sym_type (gfc_symbol * sym)
else if (sym->attr.allocatable)
akind = GFC_ARRAY_ALLOCATABLE;
type = gfc_build_array_type (type, sym->as, akind, restricted,
- sym->attr.contiguous);
+ sym->attr.contiguous, false);
}
}
else
@@ -2279,7 +2287,7 @@ gfc_add_field_to_struct (tree context, tree name, tree type, tree **chain)
tree decl = gfc_add_field_to_struct_1 (context, name, type, chain);
DECL_INITIAL (decl) = 0;
- DECL_ALIGN (decl) = 0;
+ SET_DECL_ALIGN (decl, 0);
DECL_USER_ALIGN (decl) = 0;
return decl;
@@ -2417,7 +2425,7 @@ gfc_get_union_type (gfc_symbol *un)
in a parent namespace, this is used. */
tree
-gfc_get_derived_type (gfc_symbol * derived)
+gfc_get_derived_type (gfc_symbol * derived, int codimen)
{
tree typenode = NULL, field = NULL, field_type = NULL;
tree canonical = NULL_TREE;
@@ -2521,7 +2529,11 @@ gfc_get_derived_type (gfc_symbol * derived)
non-procedure pointer components have no backend_decl. */
for (c = derived->components; c; c = c->next)
{
- if (!c->attr.proc_pointer && c->backend_decl == NULL)
+ bool same_alloc_type = c->attr.allocatable
+ && derived == c->ts.u.derived;
+ if (!c->attr.proc_pointer
+ && !same_alloc_type
+ && c->backend_decl == NULL)
break;
else if (c->next == NULL)
return derived->backend_decl;
@@ -2553,15 +2565,23 @@ gfc_get_derived_type (gfc_symbol * derived)
will be built and so we can return the type. */
for (c = derived->components; c; c = c->next)
{
+ bool same_alloc_type = c->attr.allocatable
+ && derived == c->ts.u.derived;
+
if (c->ts.type == BT_UNION && c->ts.u.derived->backend_decl == NULL)
c->ts.u.derived->backend_decl = gfc_get_union_type (c->ts.u.derived);
if (c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS)
continue;
- if ((!c->attr.pointer && !c->attr.proc_pointer)
+ if ((!c->attr.pointer && !c->attr.proc_pointer
+ && !same_alloc_type)
|| c->ts.u.derived->backend_decl == NULL)
- c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived);
+ {
+ int local_codim = c->attr.codimension ? c->as->corank: codimen;
+ c->ts.u.derived->backend_decl = gfc_get_derived_type (c->ts.u.derived,
+ local_codim);
+ }
if (c->ts.u.derived->attr.is_iso_c)
{
@@ -2591,6 +2611,8 @@ gfc_get_derived_type (gfc_symbol * derived)
types are built as part of gfc_get_union_type. */
for (c = derived->components; c; c = c->next)
{
+ bool same_alloc_type = c->attr.allocatable
+ && derived == c->ts.u.derived;
/* Prevent infinite recursion, when the procedure pointer type is
the same as derived, by forcing the procedure pointer component to
be built as if the explicit interface does not exist. */
@@ -2618,7 +2640,7 @@ gfc_get_derived_type (gfc_symbol * derived)
c->ts.u.cl->backend_decl
= build_int_cst (gfc_charlen_type_node, 0);
- field_type = gfc_typenode_for_spec (&c->ts);
+ field_type = gfc_typenode_for_spec (&c->ts, codimen);
}
/* This returns an array descriptor type. Initialization may be
@@ -2638,7 +2660,8 @@ gfc_get_derived_type (gfc_symbol * derived)
field_type = gfc_build_array_type (field_type, c->as, akind,
!c->attr.target
&& !c->attr.pointer,
- c->attr.contiguous);
+ c->attr.contiguous,
+ codimen);
}
else
field_type = gfc_get_nodesc_array_type (field_type, c->as,
@@ -2650,7 +2673,7 @@ gfc_get_derived_type (gfc_symbol * derived)
&& !(unlimited_entity && c == derived->components))
field_type = build_pointer_type (field_type);
- if (c->attr.pointer)
+ if (c->attr.pointer || same_alloc_type)
field_type = gfc_nonrestricted_type (field_type);
/* vtype fields can point to different types to the base type. */
@@ -2683,6 +2706,19 @@ gfc_get_derived_type (gfc_symbol * derived)
gcc_assert (field);
if (!c->backend_decl)
c->backend_decl = field;
+
+ /* Do not add a caf_token field for classes' data components. */
+ if (codimen && !c->attr.dimension && !c->attr.codimension
+ && (c->attr.allocatable || c->attr.pointer)
+ && c->caf_token == NULL_TREE && strcmp ("_data", c->name) != 0)
+ {
+ char caf_name[GFC_MAX_SYMBOL_LEN];
+ snprintf (caf_name, GFC_MAX_SYMBOL_LEN, "_caf_%s", c->name);
+ c->caf_token = gfc_add_field_to_struct (typenode,
+ get_identifier (caf_name),
+ pvoid_type_node, &chain);
+ TREE_NO_WARNING (c->caf_token) = 1;
+ }
}
/* Now lay out the derived type, including the fields. */
@@ -3110,7 +3146,7 @@ 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, dim_off, dim_size, elem_size;
+ tree data_off, dim_off, dtype_off, dim_size, elem_size;
tree lower_suboff, upper_suboff, stride_suboff;
if (! GFC_DESCRIPTOR_TYPE_P (type))
@@ -3159,7 +3195,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
base_decl = make_node (DEBUG_EXPR_DECL);
DECL_ARTIFICIAL (base_decl) = 1;
TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
- DECL_MODE (base_decl) = TYPE_MODE (TREE_TYPE (base_decl));
+ SET_DECL_MODE (base_decl, TYPE_MODE (TREE_TYPE (base_decl)));
GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
}
info->base_decl = base_decl;
@@ -3174,6 +3210,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
data_off = byte_position (field);
field = DECL_CHAIN (field);
field = DECL_CHAIN (field);
+ dtype_off = byte_position (field);
field = DECL_CHAIN (field);
dim_off = byte_position (field);
dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field)));
@@ -3196,6 +3233,24 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
|| GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
info->associated = build2 (NE_EXPR, boolean_type_node,
info->data_location, null_pointer_node);
+ if ((GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT)
+ && dwarf_version >= 5)
+ {
+ rank = 1;
+ info->ndimensions = 1;
+ t = base_decl;
+ if (!integer_zerop (dtype_off))
+ t = fold_build_pointer_plus (t, dtype_off);
+ t = build1 (NOP_EXPR, build_pointer_type (gfc_array_index_type), t);
+ t = build1 (INDIRECT_REF, gfc_array_index_type, t);
+ info->rank = build2 (BIT_AND_EXPR, gfc_array_index_type, t,
+ build_int_cst (gfc_array_index_type,
+ GFC_DTYPE_RANK_MASK));
+ t = build0 (PLACEHOLDER_EXPR, TREE_TYPE (dim_off));
+ t = size_binop (MULT_EXPR, t, dim_size);
+ dim_off = build2 (PLUS_EXPR, TREE_TYPE (dim_off), t, dim_off);
+ }
for (dim = 0; dim < rank; dim++)
{
@@ -3231,7 +3286,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
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);
+ if (dim + 1 < rank)
+ dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
}
return true;
@@ -3324,4 +3380,121 @@ gfc_get_caf_vector_type (int dim)
return vector_types[dim-1];
}
+
+tree
+gfc_get_caf_reference_type ()
+{
+ static tree reference_type = NULL_TREE;
+ tree c_struct_type, s_struct_type, v_struct_type, union_type, dim_union_type,
+ a_struct_type, u_union_type, tmp, *chain;
+
+ if (reference_type != NULL_TREE)
+ return reference_type;
+
+ chain = 0;
+ c_struct_type = make_node (RECORD_TYPE);
+ tmp = gfc_add_field_to_struct_1 (c_struct_type,
+ get_identifier ("offset"),
+ gfc_array_index_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (c_struct_type,
+ get_identifier ("caf_token_offset"),
+ gfc_array_index_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (c_struct_type);
+
+ chain = 0;
+ s_struct_type = make_node (RECORD_TYPE);
+ tmp = gfc_add_field_to_struct_1 (s_struct_type,
+ get_identifier ("start"),
+ gfc_array_index_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (s_struct_type,
+ get_identifier ("end"),
+ gfc_array_index_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (s_struct_type,
+ get_identifier ("stride"),
+ gfc_array_index_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (s_struct_type);
+
+ chain = 0;
+ v_struct_type = make_node (RECORD_TYPE);
+ tmp = gfc_add_field_to_struct_1 (v_struct_type,
+ get_identifier ("vector"),
+ pvoid_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (v_struct_type,
+ get_identifier ("nvec"),
+ size_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (v_struct_type,
+ get_identifier ("kind"),
+ integer_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (v_struct_type);
+
+ chain = 0;
+ union_type = make_node (UNION_TYPE);
+ tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("s"),
+ s_struct_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (union_type, get_identifier ("v"),
+ v_struct_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (union_type);
+
+ tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
+ gfc_rank_cst[GFC_MAX_DIMENSIONS - 1]);
+ dim_union_type = build_array_type (union_type, tmp);
+
+ chain = 0;
+ a_struct_type = make_node (RECORD_TYPE);
+ tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("mode"),
+ build_array_type (unsigned_char_type_node,
+ build_range_type (gfc_array_index_type,
+ gfc_index_zero_node,
+ gfc_rank_cst[GFC_MAX_DIMENSIONS - 1])),
+ &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (a_struct_type,
+ get_identifier ("static_array_type"),
+ integer_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (a_struct_type, get_identifier ("dim"),
+ dim_union_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (a_struct_type);
+
+ chain = 0;
+ u_union_type = make_node (UNION_TYPE);
+ tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("c"),
+ c_struct_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (u_union_type, get_identifier ("a"),
+ a_struct_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (u_union_type);
+
+ chain = 0;
+ reference_type = make_node (RECORD_TYPE);
+ tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("next"),
+ build_pointer_type (reference_type), &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("type"),
+ integer_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("item_size"),
+ size_type_node, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ tmp = gfc_add_field_to_struct_1 (reference_type, get_identifier ("u"),
+ u_union_type, &chain);
+ TREE_NO_WARNING (tmp) = 1;
+ gfc_finish_type (reference_type);
+ TYPE_NAME (reference_type) = get_identifier ("caf_reference_t");
+
+ return reference_type;
+}
+
#include "gt-fortran-trans-types.h"