diff options
author | tobi <tobi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-29 09:03:03 +0000 |
---|---|---|
committer | tobi <tobi@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-05-29 09:03:03 +0000 |
commit | 1318f16c5d4a4d4ce1d58fc0951ae013d145914a (patch) | |
tree | 8e4549612e4d823845bf8d6edcfa17ce896c8947 /gcc/fortran | |
parent | 8f433c51e34a5653062ecdc494079e04f3f84414 (diff) | |
download | gcc-1318f16c5d4a4d4ce1d58fc0951ae013d145914a.tar.gz |
2007-05-28 Tobias Schlter <tobi@gcc.gnu.org>
fortran/
* gfortran.h (gfc_generic_isym_id): Add GFC_ISYM_SIZEOF.
* intrinsic.c (add_functions): Add stuff for SIZEOF intrinsic.
* intrinsic.h (gfc_check_sizeof): Add prototype of ...
* check.c (gfc_check_sizeof): .. new function.
* trans-intrinsic.c (gfc_conv_intrinsic_sizeof): New function.
(gfc_conv_intrinsic_strcmp): Whitespace fix.
(gfc_conv_intrinsic_array_transfer): Remove double initialization,
use fold_build. where appropriate.
(gfc_conv_intrinsic_function): Add case for SIZEOF.
* intrinsic.texi: Add documentation for SIZEOF.
testsuite/
* gfortran.dg/sizeof.f90: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125161 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/check.c | 7 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 1 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.c | 6 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.h | 1 | ||||
-rw-r--r-- | gcc/fortran/intrinsic.texi | 44 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 128 |
7 files changed, 175 insertions, 25 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 8f0422e882f..65dfa5f5b96 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2007-05-28 Tobias Schlüter <tobi@gcc.gnu.org> + + * gfortran.h (gfc_generic_isym_id): Add GFC_ISYM_SIZEOF. + * intrinsic.c (add_functions): Add stuff for SIZEOF intrinsic. + * intrinsic.h (gfc_check_sizeof): Add prototype of ... + * check.c (gfc_check_sizeof): .. new function. + * trans-intrinsic.c (gfc_conv_intrinsic_sizeof): New function. + (gfc_conv_intrinsic_strcmp): Whitespace fix. + (gfc_conv_intrinsic_array_transfer): Remove double initialization, + use fold_build. where appropriate. + (gfc_conv_intrinsic_function): Add case for SIZEOF. + * intrinsic.texi: Add documentation for SIZEOF. + 2007-05-28 Brooks Moses <brooks.moses@codesourcery.com> * trans-array.c (gfc_conv_expr_descriptor): Edit comment. diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index e2290026714..a1966353f30 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -2334,6 +2334,13 @@ gfc_check_size (gfc_expr *array, gfc_expr *dim) try +gfc_check_sizeof (gfc_expr *arg __attribute__((unused))) +{ + return SUCCESS; +} + + +try gfc_check_sleep_sub (gfc_expr *seconds) { if (type_check (seconds, 0, BT_INTEGER) == FAILURE) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index c7fa5f8403c..e64a9957758 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -446,6 +446,7 @@ enum gfc_generic_isym_id GFC_ISYM_SIN, GFC_ISYM_SINH, GFC_ISYM_SIZE, + GFC_ISYM_SIZEOF, GFC_ISYM_SPACING, GFC_ISYM_SPREAD, GFC_ISYM_SQRT, diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index d3392b085c3..3a72fc5caaa 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -2138,6 +2138,12 @@ add_functions (void) make_generic ("size", GFC_ISYM_SIZE, GFC_STD_F95); + add_sym_1 ("sizeof", NOT_ELEMENTAL, ACTUAL_NO, BT_INTEGER, di, + GFC_STD_GNU, gfc_check_sizeof, NULL, NULL, + i, BT_INTEGER, di, REQUIRED); + + make_generic ("sizeof", GFC_ISYM_SIZEOF, GFC_STD_GNU); + add_sym_1 ("spacing", ELEMENTAL, ACTUAL_NO, BT_REAL, dr, GFC_STD_F95, gfc_check_x, gfc_simplify_spacing, gfc_resolve_spacing, x, BT_REAL, dr, REQUIRED); diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h index d4a4fc5ce85..5bc4a855971 100644 --- a/gcc/fortran/intrinsic.h +++ b/gcc/fortran/intrinsic.h @@ -121,6 +121,7 @@ try gfc_check_shape (gfc_expr *); try gfc_check_size (gfc_expr *, gfc_expr *); try gfc_check_sign (gfc_expr *, gfc_expr *); try gfc_check_signal (gfc_expr *, gfc_expr *); +try gfc_check_sizeof (gfc_expr *); try gfc_check_spread (gfc_expr *, gfc_expr *, gfc_expr *); try gfc_check_srand (gfc_expr *); try gfc_check_stat (gfc_expr *, gfc_expr *); diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi index 892fda513f4..aea18b1dc34 100644 --- a/gcc/fortran/intrinsic.texi +++ b/gcc/fortran/intrinsic.texi @@ -222,6 +222,7 @@ Some basic guidelines for editing this document: * @code{SIN}: SIN, Sine function * @code{SINH}: SINH, Hyperbolic sine function * @code{SIZE}: SIZE, Function to determine the size of an array +* @code{SIZEOF}: SIZEOF, Determine the size in bytes of an expression * @code{SLEEP}: SLEEP, Sleep for the specified number of seconds * @code{SNGL}: SNGL, Convert double precision real to default real * @code{SPACING}: SPACING, Smallest distance between two numbers of a given type @@ -9012,6 +9013,49 @@ END PROGRAM @end table +@node SIZEOF +@section @code{SIZEOF} --- Size in bytes of an expression +@fnindex SIZEOF +@cindex expression size +@cindex size of an expression + +@table @asis +@item @emph{Description}: +@code{SIZEOF(X)} calculates the number of bytes of storage the +expression @code{X} occupies. + +@item @emph{Standard}: +GNU extension + +@item @emph{Class}: +Intrinsic function + +@item @emph{Syntax}: +@code{N = SIZEOF(X)} + +@item @emph{Arguments}: +@multitable @columnfractions .15 .70 +@item @var{X} @tab The argument shall be of any type, rank or shape. +@end multitable + +@item @emph{Return value}: +The return value is of type integer. Its value is the number of bytes +occupied by the argument. If the argument has the @code{POINTER} +attribute, the number of bytes of the storage area pointed to is +returned. If the argument is of a derived type with @code{POINTER} or +@code{ALLOCATABLE} components, the return value doesn't account for +the sizes of the data pointed to by these components. + +@item @emph{Example}: +@smallexample + integer :: i + real :: r, s(5) + print *, (sizeof(s)/sizeof(r) == 5) + end +@end smallexample +The example will print @code{.TRUE.} unless you are using a platform +where default @code{REAL} variables are unusually padded. +@end table @node SLEEP @section @code{SLEEP} --- Sleep for the specified number of seconds diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index d814b28a21a..4745a78f41c 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2745,9 +2745,83 @@ gfc_conv_intrinsic_size (gfc_se * se, gfc_expr * expr) } +static void +gfc_conv_intrinsic_sizeof (gfc_se *se, gfc_expr *expr) +{ + gfc_expr *arg; + gfc_ss *ss; + gfc_se argse; + tree source; + tree source_bytes; + tree type; + tree tmp; + tree lower; + tree upper; + /*tree stride;*/ + int n; + + arg = expr->value.function.actual->expr; + + gfc_init_se (&argse, NULL); + ss = gfc_walk_expr (arg); + + source_bytes = gfc_create_var (gfc_array_index_type, "bytes"); + + if (ss == gfc_ss_terminator) + { + gfc_conv_expr_reference (&argse, arg); + source = argse.expr; + + type = TREE_TYPE (build_fold_indirect_ref (argse.expr)); + + /* Obtain the source word length. */ + if (arg->ts.type == BT_CHARACTER) + source_bytes = fold_convert (gfc_array_index_type, + argse.string_length); + else + source_bytes = fold_convert (gfc_array_index_type, + size_in_bytes (type)); + } + else + { + argse.want_pointer = 0; + gfc_conv_expr_descriptor (&argse, arg, ss); + source = gfc_conv_descriptor_data_get (argse.expr); + type = gfc_get_element_type (TREE_TYPE (argse.expr)); + + /* Obtain the argument's word length. */ + if (arg->ts.type == BT_CHARACTER) + tmp = fold_convert (gfc_array_index_type, argse.string_length); + else + tmp = fold_convert (gfc_array_index_type, + size_in_bytes (type)); + gfc_add_modify_expr (&argse.pre, source_bytes, tmp); + + /* Obtain the size of the array in bytes. */ + for (n = 0; n < arg->rank; n++) + { + tree idx; + idx = gfc_rank_cst[n]; + lower = gfc_conv_descriptor_lbound (argse.expr, idx); + upper = gfc_conv_descriptor_ubound (argse.expr, idx); + tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, + upper, lower); + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, + tmp, gfc_index_one_node); + tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, + tmp, source_bytes); + gfc_add_modify_expr (&argse.pre, source_bytes, tmp); + } + } + + gfc_add_block_to_block (&se->pre, &argse.pre); + se->expr = source_bytes; +} + + /* Intrinsic string comparison functions. */ - static void +static void gfc_conv_intrinsic_strcmp (gfc_se * se, gfc_expr * expr, int op) { tree type; @@ -2850,7 +2924,6 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) } else { - gfc_init_se (&argse, NULL); argse.want_pointer = 0; gfc_conv_expr_descriptor (&argse, arg->expr, ss); source = gfc_conv_descriptor_data_get (argse.expr); @@ -2898,13 +2971,13 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) stride = gfc_conv_descriptor_stride (argse.expr, idx); lower = gfc_conv_descriptor_lbound (argse.expr, idx); upper = gfc_conv_descriptor_ubound (argse.expr, idx); - tmp = build2 (MINUS_EXPR, gfc_array_index_type, - upper, lower); + tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, + upper, lower); gfc_add_modify_expr (&argse.pre, extent, tmp); - tmp = build2 (PLUS_EXPR, gfc_array_index_type, - extent, gfc_index_one_node); - tmp = build2 (MULT_EXPR, gfc_array_index_type, - tmp, source_bytes); + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, + extent, gfc_index_one_node); + tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, + tmp, source_bytes); } } @@ -2964,17 +3037,18 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) size_bytes = gfc_create_var (gfc_array_index_type, NULL); if (tmp != NULL_TREE) { - tmp = build2 (MULT_EXPR, gfc_array_index_type, - tmp, dest_word_len); - tmp = build2 (MIN_EXPR, gfc_array_index_type, tmp, source_bytes); + tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, + tmp, dest_word_len); + tmp = fold_build2 (MIN_EXPR, gfc_array_index_type, + tmp, source_bytes); } else tmp = source_bytes; gfc_add_modify_expr (&se->pre, size_bytes, tmp); gfc_add_modify_expr (&se->pre, size_words, - build2 (CEIL_DIV_EXPR, gfc_array_index_type, - size_bytes, dest_word_len)); + fold_build2 (CEIL_DIV_EXPR, gfc_array_index_type, + size_bytes, dest_word_len)); /* Evaluate the bounds of the result. If the loop range exists, we have to check if it is too large. If so, we modify loop->to be consistent @@ -2985,23 +3059,23 @@ gfc_conv_intrinsic_array_transfer (gfc_se * se, gfc_expr * expr) { tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, se->loop->to[n], se->loop->from[n]); - tmp = build2 (PLUS_EXPR, gfc_array_index_type, - tmp, gfc_index_one_node); - tmp = build2 (MIN_EXPR, gfc_array_index_type, - tmp, size_words); + tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, + tmp, gfc_index_one_node); + tmp = fold_build2 (MIN_EXPR, gfc_array_index_type, + tmp, size_words); gfc_add_modify_expr (&se->pre, size_words, tmp); gfc_add_modify_expr (&se->pre, size_bytes, - build2 (MULT_EXPR, gfc_array_index_type, - size_words, dest_word_len)); - upper = build2 (PLUS_EXPR, gfc_array_index_type, - size_words, se->loop->from[n]); - upper = build2 (MINUS_EXPR, gfc_array_index_type, - upper, gfc_index_one_node); + fold_build2 (MULT_EXPR, gfc_array_index_type, + size_words, dest_word_len)); + upper = fold_build2 (PLUS_EXPR, gfc_array_index_type, + size_words, se->loop->from[n]); + upper = fold_build2 (MINUS_EXPR, gfc_array_index_type, + upper, gfc_index_one_node); } else { - upper = build2 (MINUS_EXPR, gfc_array_index_type, - size_words, gfc_index_one_node); + upper = fold_build2 (MINUS_EXPR, gfc_array_index_type, + size_words, gfc_index_one_node); se->loop->from[n] = gfc_index_zero_node; } @@ -3866,6 +3940,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_size (se, expr); break; + case GFC_ISYM_SIZEOF: + gfc_conv_intrinsic_sizeof (se, expr); + break; + case GFC_ISYM_SUM: gfc_conv_intrinsic_arith (se, expr, PLUS_EXPR); break; |