OSDN Git Service

* trans.h (struct gfc_ss, struct gfc_ss_info): Move field
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-expr.c
index 131927c..01d4ca3 100644 (file)
@@ -613,6 +613,7 @@ conv_parent_component_references (gfc_se * se, gfc_ref * ref)
 static void
 gfc_conv_variable (gfc_se * se, gfc_expr * expr)
 {
+  gfc_ss *ss;
   gfc_ref *ref;
   gfc_symbol *sym;
   tree parent_decl = NULL_TREE;
@@ -622,16 +623,19 @@ gfc_conv_variable (gfc_se * se, gfc_expr * expr)
   bool entry_master;
 
   sym = expr->symtree->n.sym;
-  if (se->ss != NULL)
+  ss = se->ss;
+  if (ss != NULL)
     {
+      gfc_ss_info *ss_info = ss->info;
+
       /* Check that something hasn't gone horribly wrong.  */
-      gcc_assert (se->ss != gfc_ss_terminator);
-      gcc_assert (se->ss->expr == expr);
+      gcc_assert (ss != gfc_ss_terminator);
+      gcc_assert (ss_info->expr == expr);
 
       /* A scalarized term.  We already know the descriptor.  */
-      se->expr = se->ss->data.info.descriptor;
-      se->string_length = se->ss->string_length;
-      for (ref = se->ss->data.info.ref; ref; ref = ref->next)
+      se->expr = ss_info->data.array.descriptor;
+      se->string_length = ss_info->string_length;
+      for (ref = ss_info->data.array.ref; ref; ref = ref->next)
        if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
          break;
     }
@@ -1124,22 +1128,22 @@ gfc_conv_power_op (gfc_se * se, gfc_expr * expr)
              switch (kind)
                {
                case 0:
-                 fndecl = built_in_decls[BUILT_IN_POWIF];
+                 fndecl = builtin_decl_explicit (BUILT_IN_POWIF);
                  break;
                
                case 1:
-                 fndecl = built_in_decls[BUILT_IN_POWI];
+                 fndecl = builtin_decl_explicit (BUILT_IN_POWI);
                  break;
 
                case 2:
-                 fndecl = built_in_decls[BUILT_IN_POWIL];
+                 fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
                  break;
 
                case 3:
                  /* Use the __builtin_powil() only if real(kind=16) is 
                     actually the C long double type.  */
                  if (!gfc_real16_is_float128)
-                   fndecl = built_in_decls[BUILT_IN_POWIL];
+                   fndecl = builtin_decl_explicit (BUILT_IN_POWIL);
                  break;
 
                default:
@@ -2359,7 +2363,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
   gfc_ss *rss;
   gfc_loopinfo loop;
   gfc_loopinfo loop2;
-  gfc_ss_info *info;
+  gfc_array_info *info;
   tree offset;
   tree tmp_index;
   tree tmp;
@@ -2400,7 +2404,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
                                              : NULL),
                                  loop.dimen);
 
-  parmse->string_length = loop.temp_ss->string_length;
+  parmse->string_length = loop.temp_ss->info->string_length;
 
   /* Associate the SS with the loop.  */
   gfc_add_ss_to_loop (&loop, loop.temp_ss);
@@ -2409,7 +2413,7 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
   gfc_conv_loop_setup (&loop, &expr->where);
 
   /* Pass the temporary descriptor back to the caller.  */
-  info = &loop.temp_ss->data.info;
+  info = &loop.temp_ss->info->data.array;
   parmse->expr = info->descriptor;
 
   /* Setup the gfc_se structures.  */
@@ -2488,8 +2492,8 @@ gfc_conv_subref_array_arg (gfc_se * parmse, gfc_expr * expr, int g77,
      dimensions, so this is very simple.  The offset is only computed
      outside the innermost loop, so the overall transfer could be
      optimized further.  */
-  info = &rse.ss->data.info;
-  dimen = info->dimen;
+  info = &rse.ss->info->data.array;
+  dimen = rse.ss->dimen;
 
   tmp_index = gfc_index_zero_node;
   for (n = dimen - 1; n > 0; n--)
@@ -2854,7 +2858,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
   tree fntype;
   gfc_se parmse;
   gfc_ss *argss;
-  gfc_ss_info *info;
+  gfc_array_info *info;
   int byref;
   int parm_kind;
   tree type;
@@ -2893,8 +2897,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
     {
       if (!sym->attr.elemental)
        {
-         gcc_assert (se->ss->type == GFC_SS_FUNCTION);
-         if (se->ss->useflags)
+         gcc_assert (se->ss->info->type == GFC_SS_FUNCTION);
+         if (se->ss->info->useflags)
            {
              gcc_assert ((!comp && gfc_return_by_reference (sym)
                           && sym->result->attr.dimension)
@@ -2906,7 +2910,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
              return 0;
            }
        }
-      info = &se->ss->data.info;
+      info = &se->ss->info->data.array;
     }
   else
     info = NULL;
@@ -2979,7 +2983,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
          gfc_init_se (&parmse, se);
          gfc_conv_derived_to_class (&parmse, e, fsym->ts);
        }
-      else if (se->ss && se->ss->useflags)
+      else if (se->ss && se->ss->info->useflags)
        {
          /* An elemental function inside a scalarized loop.  */
          gfc_init_se (&parmse, se);
@@ -3357,10 +3361,16 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
              else
                goto end_pointer_check;
 
+             tmp = parmse.expr;
+
+             /* If the argument is passed by value, we need to strip the
+                INDIRECT_REF.  */
+             if (!POINTER_TYPE_P (TREE_TYPE (parmse.expr)))
+               tmp = gfc_build_addr_expr (NULL_TREE, tmp);
 
              cond = fold_build2_loc (input_location, EQ_EXPR,
-                                     boolean_type_node, parmse.expr,
-                                     fold_convert (TREE_TYPE (parmse.expr),
+                                     boolean_type_node, tmp,
+                                     fold_convert (TREE_TYPE (tmp),
                                                    null_pointer_node));
            }
  
@@ -3576,7 +3586,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 
          /* Set the type of the array.  */
          tmp = gfc_typenode_for_spec (&comp->ts);
-         gcc_assert (info->dimen == se->loop->dimen);
+         gcc_assert (se->ss->dimen == se->loop->dimen);
 
          /* Evaluate the bounds of the result, if known.  */
          gfc_set_loop_bounds_from_array_spec (&mapping, se, comp->as);
@@ -3596,9 +3606,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
             returns a pointer, the temporary will be a shallow copy and
             mustn't be deallocated.  */
          callee_alloc = comp->attr.allocatable || comp->attr.pointer;
-         gfc_trans_create_temp_array (&se->pre, &se->post, se->loop, info, tmp,
-                                      NULL_TREE, false, !comp->attr.pointer,
-                                      callee_alloc, &se->ss->expr->where);
+         gfc_trans_create_temp_array (&se->pre, &se->post, se->loop, se->ss,
+                                      tmp, NULL_TREE, false,
+                                      !comp->attr.pointer, callee_alloc,
+                                      &se->ss->info->expr->where);
 
          /* Pass the temporary as the first argument.  */
          result = info->descriptor;
@@ -3611,7 +3622,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
 
          /* Set the type of the array.  */
          tmp = gfc_typenode_for_spec (&ts);
-         gcc_assert (info->dimen == se->loop->dimen);
+         gcc_assert (se->ss->dimen == se->loop->dimen);
 
          /* Evaluate the bounds of the result, if known.  */
          gfc_set_loop_bounds_from_array_spec (&mapping, se, sym->result->as);
@@ -3631,9 +3642,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
             returns a pointer, the temporary will be a shallow copy and
             mustn't be deallocated.  */
          callee_alloc = sym->attr.allocatable || sym->attr.pointer;
-         gfc_trans_create_temp_array (&se->pre, &se->post, se->loop, info, tmp,
-                                      NULL_TREE, false, !sym->attr.pointer,
-                                      callee_alloc, &se->ss->expr->where);
+         gfc_trans_create_temp_array (&se->pre, &se->post, se->loop, se->ss,
+                                      tmp, NULL_TREE, false,
+                                      !sym->attr.pointer, callee_alloc,
+                                      &se->ss->info->expr->where);
 
          /* Pass the temporary as the first argument.  */
          result = info->descriptor;
@@ -3855,7 +3867,8 @@ fill_with_spaces (tree start, tree type, tree size)
   /* For a simple char type, we can call memset().  */
   if (compare_tree_int (TYPE_SIZE_UNIT (type), 1) == 0)
     return build_call_expr_loc (input_location,
-                           built_in_decls[BUILT_IN_MEMSET], 3, start,
+                           builtin_decl_explicit (BUILT_IN_MEMSET),
+                           3, start,
                            build_int_cst (gfc_get_int_type (gfc_c_int_kind),
                                           lang_hooks.to_target_charset (' ')),
                            size);
@@ -4015,13 +4028,13 @@ gfc_trans_string_copy (stmtblock_t * block, tree dlength, tree dest,
   cond2 = fold_build2_loc (input_location, GE_EXPR, boolean_type_node, slen,
                           dlen);
   tmp2 = build_call_expr_loc (input_location,
-                         built_in_decls[BUILT_IN_MEMMOVE],
-                         3, dest, src, dlen);
+                             builtin_decl_explicit (BUILT_IN_MEMMOVE),
+                             3, dest, src, dlen);
 
   /* Else copy and pad with spaces.  */
   tmp3 = build_call_expr_loc (input_location,
-                         built_in_decls[BUILT_IN_MEMMOVE],
-                         3, dest, src, slen);
+                             builtin_decl_explicit (BUILT_IN_MEMMOVE),
+                             3, dest, src, slen);
 
   tmp4 = fold_build_pointer_plus_loc (input_location, dest, slen);
   tmp4 = fill_with_spaces (tmp4, chartype,
@@ -4230,8 +4243,11 @@ is_zero_initializer_p (gfc_expr * expr)
 static void
 gfc_conv_array_constructor_expr (gfc_se * se, gfc_expr * expr)
 {
-  gcc_assert (se->ss != NULL && se->ss != gfc_ss_terminator);
-  gcc_assert (se->ss->expr == expr && se->ss->type == GFC_SS_CONSTRUCTOR);
+  gfc_ss *ss;
+
+  ss = se->ss;
+  gcc_assert (ss != NULL && ss != gfc_ss_terminator);
+  gcc_assert (ss->info->expr == expr && ss->info->type == GFC_SS_CONSTRUCTOR);
 
   gfc_conv_tmp_array_ref (se);
 }
@@ -4335,6 +4351,7 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
   gfc_se lse;
   gfc_ss *rss;
   gfc_ss *lss;
+  gfc_array_info *lss_array;
   stmtblock_t body;
   stmtblock_t block;
   gfc_loopinfo loop;
@@ -4358,19 +4375,20 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
   /* Create a SS for the destination.  */
   lss = gfc_get_array_ss (gfc_ss_terminator, NULL, cm->as->rank,
                          GFC_SS_COMPONENT);
-  lss->shape = gfc_get_shape (cm->as->rank);
-  lss->data.info.descriptor = dest;
-  lss->data.info.data = gfc_conv_array_data (dest);
-  lss->data.info.offset = gfc_conv_array_offset (dest);
+  lss_array = &lss->info->data.array;
+  lss_array->shape = gfc_get_shape (cm->as->rank);
+  lss_array->descriptor = dest;
+  lss_array->data = gfc_conv_array_data (dest);
+  lss_array->offset = gfc_conv_array_offset (dest);
   for (n = 0; n < cm->as->rank; n++)
     {
-      lss->data.info.start[n] = gfc_conv_array_lbound (dest, n);
-      lss->data.info.stride[n] = gfc_index_one_node;
+      lss_array->start[n] = gfc_conv_array_lbound (dest, n);
+      lss_array->stride[n] = gfc_index_one_node;
 
-      mpz_init (lss->shape[n]);
-      mpz_sub (lss->shape[n], cm->as->upper[n]->value.integer,
+      mpz_init (lss_array->shape[n]);
+      mpz_sub (lss_array->shape[n], cm->as->upper[n]->value.integer,
               cm->as->lower[n]->value.integer);
-      mpz_add_ui (lss->shape[n], lss->shape[n], 1);
+      mpz_add_ui (lss_array->shape[n], lss_array->shape[n], 1);
     }
   
   /* Associate the SS with the loop.  */
@@ -4413,8 +4431,8 @@ gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr)
   gfc_add_block_to_block (&block, &loop.pre);
   gfc_add_block_to_block (&block, &loop.post);
 
-  gcc_assert (lss->shape != NULL);
-  gfc_free_shape (&lss->shape, cm->as->rank);
+  gcc_assert (lss_array->shape != NULL);
+  gfc_free_shape (&lss_array->shape, cm->as->rank);
   gfc_cleanup_loop (&loop);
 
   return gfc_finish_block (&block);
@@ -4810,15 +4828,22 @@ gfc_conv_substring_expr (gfc_se * se, gfc_expr * expr)
 void
 gfc_conv_expr (gfc_se * se, gfc_expr * expr)
 {
-  if (se->ss && se->ss->expr == expr
-      && (se->ss->type == GFC_SS_SCALAR || se->ss->type == GFC_SS_REFERENCE))
+  gfc_ss *ss;
+
+  ss = se->ss;
+  if (ss && ss->info->expr == expr
+      && (ss->info->type == GFC_SS_SCALAR
+         || ss->info->type == GFC_SS_REFERENCE))
     {
+      gfc_ss_info *ss_info;
+
+      ss_info = ss->info;
       /* Substitute a scalar expression evaluated outside the scalarization
          loop.  */
-      se->expr = se->ss->data.scalar.expr;
-      if (se->ss->type == GFC_SS_REFERENCE)
+      se->expr = ss_info->data.scalar.value;
+      if (ss_info->type == GFC_SS_REFERENCE)
        se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
-      se->string_length = se->ss->string_length;
+      se->string_length = ss_info->string_length;
       gfc_advance_se_ss_chain (se);
       return;
     }
@@ -4935,10 +4960,12 @@ gfc_conv_expr_type (gfc_se * se, gfc_expr * expr, tree type)
 void
 gfc_conv_expr_reference (gfc_se * se, gfc_expr * expr)
 {
+  gfc_ss *ss;
   tree var;
 
-  if (se->ss && se->ss->expr == expr
-      && se->ss->type == GFC_SS_REFERENCE)
+  ss = se->ss;
+  if (ss && ss->info->expr == expr
+      && ss->info->type == GFC_SS_REFERENCE)
     {
       /* Returns a reference to the scalar evaluated outside the loop
         for this case.  */
@@ -5816,8 +5843,8 @@ gfc_trans_zero_assign (gfc_expr * expr)
 
   /* Construct call to __builtin_memset.  */
   tmp = build_call_expr_loc (input_location,
-                        built_in_decls[BUILT_IN_MEMSET],
-                        3, dest, integer_zero_node, len);
+                            builtin_decl_explicit (BUILT_IN_MEMSET),
+                            3, dest, integer_zero_node, len);
   return fold_convert (void_type_node, tmp);
 }
 
@@ -5845,7 +5872,8 @@ gfc_build_memcpy_call (tree dst, tree src, tree len)
 
   /* Construct call to __builtin_memcpy.  */
   tmp = build_call_expr_loc (input_location,
-                        built_in_decls[BUILT_IN_MEMCPY], 3, dst, src, len);
+                            builtin_decl_explicit (BUILT_IN_MEMCPY),
+                            3, dst, src, len);
   return fold_convert (void_type_node, tmp);
 }
 
@@ -6056,8 +6084,8 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
     }
 
   tmp = build_call_expr_loc (input_location,
-                            built_in_decls[BUILT_IN_MALLOC], 1,
-                            size_in_bytes);
+                            builtin_decl_explicit (BUILT_IN_MALLOC),
+                            1, size_in_bytes);
   tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
   gfc_add_modify (block, lse.expr, tmp);
   if (expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
@@ -6083,8 +6111,8 @@ alloc_scalar_allocatable_for_assignment (stmtblock_t *block,
                      build_empty_stmt (input_location));
       gfc_add_expr_to_block (block, tmp);
       tmp = build_call_expr_loc (input_location,
-                                built_in_decls[BUILT_IN_REALLOC], 2,
-                                fold_convert (pvoid_type_node, lse.expr),
+                                builtin_decl_explicit (BUILT_IN_REALLOC),
+                                2, fold_convert (pvoid_type_node, lse.expr),
                                 size_in_bytes);
       tmp = fold_convert (TREE_TYPE (lse.expr), tmp);
       gfc_add_modify (block, lse.expr, tmp);
@@ -6142,7 +6170,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
 
       /* Find a non-scalar SS from the lhs.  */
       while (lss_section != gfc_ss_terminator
-            && lss_section->type != GFC_SS_SECTION)
+            && lss_section->info->type != GFC_SS_SECTION)
        lss_section = lss_section->next;
 
       gcc_assert (lss_section != gfc_ss_terminator);