⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trans-array.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Array translation routines   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.   Contributed by Paul Brook <paul@nowt.org>   and Steven Bosscher <s.bosscher@student.tudelft.nl>This file is part of GCC.GCC is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.GCC is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public Licensealong with GCC; see the file COPYING.  If not, write to the FreeSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA02110-1301, USA.  *//* trans-array.c-- Various array related code, including scalarization,                   allocation, initialization and other support routines.  *//* How the scalarizer works.   In gfortran, array expressions use the same core routines as scalar   expressions.   First, a Scalarization State (SS) chain is built.  This is done by walking   the expression tree, and building a linear list of the terms in the   expression.  As the tree is walked, scalar subexpressions are translated.   The scalarization parameters are stored in a gfc_loopinfo structure.   First the start and stride of each term is calculated by   gfc_conv_ss_startstride.  During this process the expressions for the array   descriptors and data pointers are also translated.   If the expression is an assignment, we must then resolve any dependencies.   In fortran all the rhs values of an assignment must be evaluated before   any assignments take place.  This can require a temporary array to store the   values.  We also require a temporary when we are passing array expressions   or vector subecripts as procedure parameters.   Array sections are passed without copying to a temporary.  These use the   scalarizer to determine the shape of the section.  The flag   loop->array_parameter tells the scalarizer that the actual values and loop   variables will not be required.   The function gfc_conv_loop_setup generates the scalarization setup code.   It determines the range of the scalarizing loop variables.  If a temporary   is required, this is created and initialized.  Code for scalar expressions   taken outside the loop is also generated at this time.  Next the offset and   scaling required to translate from loop variables to array indices for each   term is calculated.   A call to gfc_start_scalarized_body marks the start of the scalarized   expression.  This creates a scope and declares the loop variables.  Before   calling this gfc_make_ss_chain_used must be used to indicate which terms   will be used inside this loop.   The scalar gfc_conv_* functions are then used to build the main body of the   scalarization loop.  Scalarization loop variables and precalculated scalar   values are automatically substituted.  Note that gfc_advance_se_ss_chain   must be used, rather than changing the se->ss directly.   For assignment expressions requiring a temporary two sub loops are   generated.  The first stores the result of the expression in the temporary,   the second copies it to the result.  A call to   gfc_trans_scalarized_loop_boundary marks the end of the main loop code and   the start of the copying loop.  The temporary may be less than full rank.   Finally gfc_trans_scalarizing_loops is called to generate the implicit do   loops.  The loops are added to the pre chain of the loopinfo.  The post   chain may still contain cleanup code.   After the loop code has been added into its parent scope gfc_cleanup_loop   is called to free all the SS allocated by the scalarizer.  */#include "config.h"#include "system.h"#include "coretypes.h"#include "tree.h"#include "tree-gimple.h"#include "ggc.h"#include "toplev.h"#include "real.h"#include "flags.h"#include "gfortran.h"#include "trans.h"#include "trans-stmt.h"#include "trans-types.h"#include "trans-array.h"#include "trans-const.h"#include "dependency.h"static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor *);/* The contents of this structure aren't actually used, just the address.  */static gfc_ss gfc_ss_terminator_var;gfc_ss * const gfc_ss_terminator = &gfc_ss_terminator_var;static treegfc_array_dataptr_type (tree desc){  return (GFC_TYPE_ARRAY_DATAPTR_TYPE (TREE_TYPE (desc)));}/* Build expressions to access the members of an array descriptor.   It's surprisingly easy to mess up here, so never access   an array descriptor by "brute force", always use these   functions.  This also avoids problems if we change the format   of an array descriptor.   To understand these magic numbers, look at the comments   before gfc_build_array_type() in trans-types.c.   The code within these defines should be the only code which knows the format   of an array descriptor.   Any code just needing to read obtain the bounds of an array should use   gfc_conv_array_* rather than the following functions as these will return   know constant values, and work with arrays which do not have descriptors.   Don't forget to #undef these!  */#define DATA_FIELD 0#define OFFSET_FIELD 1#define DTYPE_FIELD 2#define DIMENSION_FIELD 3#define STRIDE_SUBFIELD 0#define LBOUND_SUBFIELD 1#define UBOUND_SUBFIELD 2/* This provides READ-ONLY access to the data field.  The field itself   doesn't have the proper type.  */treegfc_conv_descriptor_data_get (tree desc){  tree field, type, t;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = TYPE_FIELDS (type);  gcc_assert (DATA_FIELD == 0);  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);  t = fold_convert (GFC_TYPE_ARRAY_DATAPTR_TYPE (type), t);  return t;}/* This provides WRITE access to the data field.  */voidgfc_conv_descriptor_data_set (stmtblock_t *block, tree desc, tree value){  tree field, type, t;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = TYPE_FIELDS (type);  gcc_assert (DATA_FIELD == 0);  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);  gfc_add_modify_expr (block, t, fold_convert (TREE_TYPE (field), value));}/* This provides address access to the data field.  This should only be   used by array allocation, passing this on to the runtime.  */treegfc_conv_descriptor_data_addr (tree desc){  tree field, type, t;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = TYPE_FIELDS (type);  gcc_assert (DATA_FIELD == 0);  t = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);  return gfc_build_addr_expr (NULL, t);}treegfc_conv_descriptor_offset (tree desc){  tree type;  tree field;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = gfc_advance_chain (TYPE_FIELDS (type), OFFSET_FIELD);  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);  return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);}treegfc_conv_descriptor_dtype (tree desc){  tree field;  tree type;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = gfc_advance_chain (TYPE_FIELDS (type), DTYPE_FIELD);  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);  return build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);}static treegfc_conv_descriptor_dimension (tree desc, tree dim){  tree field;  tree type;  tree tmp;  type = TREE_TYPE (desc);  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  field = gfc_advance_chain (TYPE_FIELDS (type), DIMENSION_FIELD);  gcc_assert (field != NULL_TREE	  && TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE	  && TREE_CODE (TREE_TYPE (TREE_TYPE (field))) == RECORD_TYPE);  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), desc, field, NULL_TREE);  tmp = gfc_build_array_ref (tmp, dim);  return tmp;}treegfc_conv_descriptor_stride (tree desc, tree dim){  tree tmp;  tree field;  tmp = gfc_conv_descriptor_dimension (desc, dim);  field = TYPE_FIELDS (TREE_TYPE (tmp));  field = gfc_advance_chain (field, STRIDE_SUBFIELD);  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);  return tmp;}treegfc_conv_descriptor_lbound (tree desc, tree dim){  tree tmp;  tree field;  tmp = gfc_conv_descriptor_dimension (desc, dim);  field = TYPE_FIELDS (TREE_TYPE (tmp));  field = gfc_advance_chain (field, LBOUND_SUBFIELD);  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);  return tmp;}treegfc_conv_descriptor_ubound (tree desc, tree dim){  tree tmp;  tree field;  tmp = gfc_conv_descriptor_dimension (desc, dim);  field = TYPE_FIELDS (TREE_TYPE (tmp));  field = gfc_advance_chain (field, UBOUND_SUBFIELD);  gcc_assert (field != NULL_TREE && TREE_TYPE (field) == gfc_array_index_type);  tmp = build3 (COMPONENT_REF, TREE_TYPE (field), tmp, field, NULL_TREE);  return tmp;}/* Build a null array descriptor constructor.  */treegfc_build_null_descriptor (tree type){  tree field;  tree tmp;  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));  gcc_assert (DATA_FIELD == 0);  field = TYPE_FIELDS (type);  /* Set a NULL data pointer.  */  tmp = build_constructor_single (type, field, null_pointer_node);  TREE_CONSTANT (tmp) = 1;  TREE_INVARIANT (tmp) = 1;  /* All other fields are ignored.  */  return tmp;}/* Cleanup those #defines.  */#undef DATA_FIELD#undef OFFSET_FIELD#undef DTYPE_FIELD#undef DIMENSION_FIELD#undef STRIDE_SUBFIELD#undef LBOUND_SUBFIELD#undef UBOUND_SUBFIELD/* Mark a SS chain as used.  Flags specifies in which loops the SS is used.   flags & 1 = Main loop body.   flags & 2 = temp copy loop.  */voidgfc_mark_ss_chain_used (gfc_ss * ss, unsigned flags){  for (; ss != gfc_ss_terminator; ss = ss->next)    ss->useflags = flags;}static void gfc_free_ss (gfc_ss *);/* Free a gfc_ss chain.  */static voidgfc_free_ss_chain (gfc_ss * ss){  gfc_ss *next;  while (ss != gfc_ss_terminator)    {      gcc_assert (ss != NULL);      next = ss->next;      gfc_free_ss (ss);      ss = next;    }}/* Free a SS.  */static voidgfc_free_ss (gfc_ss * ss){  int n;  switch (ss->type)    {    case GFC_SS_SECTION:      for (n = 0; n < GFC_MAX_DIMENSIONS; n++)	{	  if (ss->data.info.subscript[n])	    gfc_free_ss_chain (ss->data.info.subscript[n]);	}      break;    default:      break;    }  gfc_free (ss);}/* Free all the SS associated with a loop.  */voidgfc_cleanup_loop (gfc_loopinfo * loop){  gfc_ss *ss;  gfc_ss *next;  ss = loop->ss;  while (ss != gfc_ss_terminator)    {      gcc_assert (ss != NULL);      next = ss->loop_chain;      gfc_free_ss (ss);      ss = next;    }}/* Associate a SS chain with a loop.  */voidgfc_add_ss_to_loop (gfc_loopinfo * loop, gfc_ss * head){  gfc_ss *ss;  if (head == gfc_ss_terminator)    return;  ss = head;  for (; ss && ss != gfc_ss_terminator; ss = ss->next)    {      if (ss->next == gfc_ss_terminator)	ss->loop_chain = loop->ss;      else	ss->loop_chain = ss->next;    }  gcc_assert (ss == gfc_ss_terminator);  loop->ss = head;}/* Generate an initializer for a static pointer or allocatable array.  */voidgfc_trans_static_array_pointer (gfc_symbol * sym){  tree type;  gcc_assert (TREE_STATIC (sym->backend_decl));  /* Just zero the data member.  */  type = TREE_TYPE (sym->backend_decl);  DECL_INITIAL (sym->backend_decl) = gfc_build_null_descriptor (type);}/* If the bounds of SE's loop have not yet been set, see if they can be   determined from array spec AS, which is the array spec of a called   function.  MAPPING maps the callee's dummy arguments to the values   that the caller is passing.  Add any initialization and finalization   code to SE.  */voidgfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,				     gfc_se * se, gfc_array_spec * as){  int n, dim;  gfc_se tmpse;  tree lower;  tree upper;  tree tmp;  if (as && as->type == AS_EXPLICIT)    for (dim = 0; dim < se->loop->dimen; dim++)      {	n = se->loop->order[dim];	if (se->loop->to[n] == NULL_TREE)	  {	    /* Evaluate the lower bound.  */	    gfc_init_se (&tmpse, NULL);	    gfc_apply_interface_mapping (mapping, &tmpse, as->lower[dim]);	    gfc_add_block_to_block (&se->pre, &tmpse.pre);	    gfc_add_block_to_block (&se->post, &tmpse.post);	    lower = tmpse.expr;	    /* ...and the upper bound.  */	    gfc_init_se (&tmpse, NULL);	    gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);	    gfc_add_block_to_block (&se->pre, &tmpse.pre);	    gfc_add_block_to_block (&se->post, &tmpse.post);	    upper = tmpse.expr;	    /* Set the upper bound of the loop to UPPER - LOWER.  */	    tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, upper, lower);	    tmp = gfc_evaluate_now (tmp, &se->pre);	    se->loop->to[n] = tmp;	  }      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -