Patchwork [Fortran] Implement RANK

login
register
mail settings
Submitter Tobias Burnus
Date June 16, 2012, 11:08 a.m.
Message ID <4FDC6918.4060706@net-b.de>
Download mbox | patch
Permalink /patch/165289/
State New
Headers show

Comments

Tobias Burnus - June 16, 2012, 11:08 a.m.
This patch adds run-time support for the RANK intrinsic. That's 
currently a bit pointless as the rank is known at compile time and, 
thus, the new code is unreachable as simplify.c handles it.

However, it becomes useful for assumed-rank arrays ("dimension(..)") of 
TS 29113. I tested it by disabling the simplify.c's version and with my 
incomplete draft patch for "(..)".

Build and regtested on x86-64-gnu-linux.
OK for the trunk?

Tobias
Paul Richard Thomas - June 18, 2012, 6:10 p.m.
Hi Tobias,


>
> Build and regtested on x86-64-gnu-linux.
> OK for the trunk?

Yes, of course it's OK for trunk.  It verges on obvious!

Thanks

Paul

Patch

2012-06-16  Tobias Burnus  <burnus@net-b.de>

	* intrinsic.h (gfc_resolve_rank): New prototype.
	* intrinsic.c (add_functions): Use gfc_resolve_rank.
	* iresolve.c (add_functions): New function.
	* trans-intrinsic.c (gfc_conv_intrinsic_rank): New function.
	(gfc_conv_intrinsic_function): Call it.

diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 38bcb27..88d4636 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -2434,7 +2434,7 @@  add_functions (void)
   make_generic ("range", GFC_ISYM_RANGE, GFC_STD_F95);
 
   add_sym_1 ("rank", GFC_ISYM_RANK, CLASS_INQUIRY, ACTUAL_NO, BT_INTEGER, di,
-	     GFC_STD_F2008_TS, gfc_check_rank, gfc_simplify_rank, NULL,
+	     GFC_STD_F2008_TS, gfc_check_rank, gfc_simplify_rank, gfc_resolve_rank,
 	     a, BT_REAL, dr, REQUIRED);
   make_generic ("rank", GFC_ISYM_RANK, GFC_STD_F2008_TS);
 
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index bfc2455..2635ba6 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -486,6 +486,7 @@  void gfc_resolve_long (gfc_expr *, gfc_expr *);
 void gfc_resolve_ior (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_iparity (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_isatty (gfc_expr *, gfc_expr *);
+void gfc_resolve_rank (gfc_expr *, gfc_expr *);
 void gfc_resolve_rshift (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_lshift (gfc_expr *, gfc_expr *, gfc_expr *);
 void gfc_resolve_ishft (gfc_expr *, gfc_expr *, gfc_expr *);
diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c
index 9d94e3b..2a49455 100644
--- a/gcc/fortran/iresolve.c
+++ b/gcc/fortran/iresolve.c
@@ -2006,6 +2006,15 @@  gfc_resolve_product (gfc_expr *f, gfc_expr *array, gfc_expr *dim,
 
 
 void
+gfc_resolve_rank (gfc_expr *f, gfc_expr *array ATTRIBUTE_UNUSED)
+{
+  f->ts.type = BT_INTEGER;
+  f->ts.kind = gfc_default_integer_kind;
+  f->value.function.name = gfc_get_string ("__rank");
+}
+
+
+void
 gfc_resolve_real (gfc_expr *f, gfc_expr *a, gfc_expr *kind)
 {
   f->ts.type = BT_REAL;
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 04d6caa..bd6f600 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -1663,6 +1663,32 @@  conv_intrinsic_cobound (gfc_se * se, gfc_expr * expr)
 
 
 static void
+gfc_conv_intrinsic_rank (gfc_se *se, gfc_expr *expr)
+{
+  gfc_se argse;
+  gfc_ss *ss;
+  tree dtype, tmp;
+
+  ss = gfc_walk_expr (expr->value.function.actual->expr);
+  gcc_assert (ss != gfc_ss_terminator);
+  gfc_init_se (&argse, NULL);
+  argse.data_not_needed = 1;
+  argse.want_pointer = 1;
+
+  gfc_conv_expr_descriptor (&argse, expr->value.function.actual->expr, ss);
+  gfc_add_block_to_block (&se->pre, &argse.pre);
+  gfc_add_block_to_block (&se->post, &argse.post);
+  argse.expr = build_fold_indirect_ref_loc (input_location, argse.expr);
+  argse.expr = build_fold_indirect_ref_loc (input_location, argse.expr);
+  dtype = gfc_conv_descriptor_dtype (argse.expr);
+  tmp = build_int_cst (TREE_TYPE (dtype), GFC_DTYPE_RANK_MASK);
+  tmp = fold_build2_loc (input_location, BIT_AND_EXPR, TREE_TYPE (dtype),
+			 dtype, tmp);
+  se->expr = fold_convert (gfc_get_int_type (gfc_default_integer_kind), tmp);
+}
+
+
+static void
 gfc_conv_intrinsic_abs (gfc_se * se, gfc_expr * expr)
 {
   tree arg, cabs;
@@ -6710,6 +6736,10 @@  gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr)
       gfc_conv_intrinsic_arith (se, expr, MULT_EXPR, false);
       break;
 
+    case GFC_ISYM_RANK:
+      gfc_conv_intrinsic_rank (se, expr);
+      break;
+
     case GFC_ISYM_RRSPACING:
       gfc_conv_intrinsic_rrspacing (se, expr);
       break;