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

📄 trans-expr.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
      return;    case INTRINSIC_PLUS:      code = PLUS_EXPR;      break;    case INTRINSIC_MINUS:      code = MINUS_EXPR;      break;    case INTRINSIC_TIMES:      code = MULT_EXPR;      break;    case INTRINSIC_DIVIDE:      /* If expr is a real or complex expr, use an RDIV_EXPR. If op1 is         an integer, we must round towards zero, so we use a         TRUNC_DIV_EXPR.  */      if (expr->ts.type == BT_INTEGER)	code = TRUNC_DIV_EXPR;      else	code = RDIV_EXPR;      break;    case INTRINSIC_POWER:      gfc_conv_power_op (se, expr);      return;    case INTRINSIC_CONCAT:      gfc_conv_concat_op (se, expr);      return;    case INTRINSIC_AND:      code = TRUTH_ANDIF_EXPR;      lop = 1;      break;    case INTRINSIC_OR:      code = TRUTH_ORIF_EXPR;      lop = 1;      break;      /* EQV and NEQV only work on logicals, but since we represent them         as integers, we can use EQ_EXPR and NE_EXPR for them in GIMPLE.  */    case INTRINSIC_EQ:    case INTRINSIC_EQV:      code = EQ_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_NE:    case INTRINSIC_NEQV:      code = NE_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_GT:      code = GT_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_GE:      code = GE_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_LT:      code = LT_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_LE:      code = LE_EXPR;      checkstring = 1;      lop = 1;      break;    case INTRINSIC_USER:    case INTRINSIC_ASSIGN:      /* These should be converted into function calls by the frontend.  */      gcc_unreachable ();    default:      fatal_error ("Unknown intrinsic op");      return;    }  /* The only exception to this is **, which is handled separately anyway.  */  gcc_assert (expr->value.op.op1->ts.type == expr->value.op.op2->ts.type);  if (checkstring && expr->value.op.op1->ts.type != BT_CHARACTER)    checkstring = 0;  /* lhs */  gfc_init_se (&lse, se);  gfc_conv_expr (&lse, expr->value.op.op1);  gfc_add_block_to_block (&se->pre, &lse.pre);  /* rhs */  gfc_init_se (&rse, se);  gfc_conv_expr (&rse, expr->value.op.op2);  gfc_add_block_to_block (&se->pre, &rse.pre);  if (checkstring)    {      gfc_conv_string_parameter (&lse);      gfc_conv_string_parameter (&rse);      lse.expr = gfc_build_compare_string (lse.string_length, lse.expr, 					   rse.string_length, rse.expr);      rse.expr = integer_zero_node;      gfc_add_block_to_block (&lse.post, &rse.post);    }  type = gfc_typenode_for_spec (&expr->ts);  if (lop)    {      /* The result of logical ops is always boolean_type_node.  */      tmp = fold_build2 (code, type, lse.expr, rse.expr);      se->expr = convert (type, tmp);    }  else    se->expr = fold_build2 (code, type, lse.expr, rse.expr);  /* Add the post blocks.  */  gfc_add_block_to_block (&se->post, &rse.post);  gfc_add_block_to_block (&se->post, &lse.post);}/* If a string's length is one, we convert it to a single character.  */static treegfc_to_single_character (tree len, tree str){  gcc_assert (POINTER_TYPE_P (TREE_TYPE (str)));  if (INTEGER_CST_P (len) && TREE_INT_CST_LOW (len) == 1    && TREE_INT_CST_HIGH (len) == 0)    {      str = fold_convert (pchar_type_node, str);      return build_fold_indirect_ref (str);    }  return NULL_TREE;}/* Compare two strings. If they are all single characters, the result is the   subtraction of them. Otherwise, we build a library call.  */treegfc_build_compare_string (tree len1, tree str1, tree len2, tree str2){  tree sc1;  tree sc2;  tree type;  tree tmp;  gcc_assert (POINTER_TYPE_P (TREE_TYPE (str1)));  gcc_assert (POINTER_TYPE_P (TREE_TYPE (str2)));  type = gfc_get_int_type (gfc_default_integer_kind);  sc1 = gfc_to_single_character (len1, str1);  sc2 = gfc_to_single_character (len2, str2);  /* Deal with single character specially.  */  if (sc1 != NULL_TREE && sc2 != NULL_TREE)    {      sc1 = fold_convert (type, sc1);      sc2 = fold_convert (type, sc2);      tmp = fold_build2 (MINUS_EXPR, type, sc1, sc2);    }   else    {      tmp = NULL_TREE;      tmp = gfc_chainon_list (tmp, len1);      tmp = gfc_chainon_list (tmp, str1);      tmp = gfc_chainon_list (tmp, len2);      tmp = gfc_chainon_list (tmp, str2);      /* Build a call for the comparison.  */      tmp = build_function_call_expr (gfor_fndecl_compare_string, tmp);    }  return tmp;}static voidgfc_conv_function_val (gfc_se * se, gfc_symbol * sym){  tree tmp;  if (sym->attr.dummy)    {      tmp = gfc_get_symbol_decl (sym);      gcc_assert (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE	      && TREE_CODE (TREE_TYPE (TREE_TYPE (tmp))) == FUNCTION_TYPE);    }  else    {      if (!sym->backend_decl)	sym->backend_decl = gfc_get_extern_function_decl (sym);      tmp = sym->backend_decl;      if (!POINTER_TYPE_P (TREE_TYPE (tmp)))	{	  gcc_assert (TREE_CODE (tmp) == FUNCTION_DECL);	  tmp = gfc_build_addr_expr (NULL, tmp);	}    }  se->expr = tmp;}/* Initialize MAPPING.  */voidgfc_init_interface_mapping (gfc_interface_mapping * mapping){  mapping->syms = NULL;  mapping->charlens = NULL;}/* Free all memory held by MAPPING (but not MAPPING itself).  */voidgfc_free_interface_mapping (gfc_interface_mapping * mapping){  gfc_interface_sym_mapping *sym;  gfc_interface_sym_mapping *nextsym;  gfc_charlen *cl;  gfc_charlen *nextcl;  for (sym = mapping->syms; sym; sym = nextsym)    {      nextsym = sym->next;      gfc_free_symbol (sym->new->n.sym);      gfc_free (sym->new);      gfc_free (sym);    }  for (cl = mapping->charlens; cl; cl = nextcl)    {      nextcl = cl->next;      gfc_free_expr (cl->length);      gfc_free (cl);    }}/* Return a copy of gfc_charlen CL.  Add the returned structure to   MAPPING so that it will be freed by gfc_free_interface_mapping.  */static gfc_charlen *gfc_get_interface_mapping_charlen (gfc_interface_mapping * mapping,				   gfc_charlen * cl){  gfc_charlen *new;  new = gfc_get_charlen ();  new->next = mapping->charlens;  new->length = gfc_copy_expr (cl->length);  mapping->charlens = new;  return new;}/* A subroutine of gfc_add_interface_mapping.  Return a descriptorless   array variable that can be used as the actual argument for dummy   argument SYM.  Add any initialization code to BLOCK.  PACKED is as   for gfc_get_nodesc_array_type and DATA points to the first element   in the passed array.  */static treegfc_get_interface_mapping_array (stmtblock_t * block, gfc_symbol * sym,				 int packed, tree data){  tree type;  tree var;  type = gfc_typenode_for_spec (&sym->ts);  type = gfc_get_nodesc_array_type (type, sym->as, packed);  var = gfc_create_var (type, "ifm");  gfc_add_modify_expr (block, var, fold_convert (type, data));  return var;}/* A subroutine of gfc_add_interface_mapping.  Set the stride, upper bounds   and offset of descriptorless array type TYPE given that it has the same   size as DESC.  Add any set-up code to BLOCK.  */static voidgfc_set_interface_mapping_bounds (stmtblock_t * block, tree type, tree desc){  int n;  tree dim;  tree offset;  tree tmp;  offset = gfc_index_zero_node;  for (n = 0; n < GFC_TYPE_ARRAY_RANK (type); n++)    {      GFC_TYPE_ARRAY_STRIDE (type, n) = gfc_conv_array_stride (desc, n);      if (GFC_TYPE_ARRAY_UBOUND (type, n) == NULL_TREE)	{	  dim = gfc_rank_cst[n];	  tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,			     gfc_conv_descriptor_ubound (desc, dim),			     gfc_conv_descriptor_lbound (desc, dim));	  tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,			     GFC_TYPE_ARRAY_LBOUND (type, n),			     tmp);	  tmp = gfc_evaluate_now (tmp, block);	  GFC_TYPE_ARRAY_UBOUND (type, n) = tmp;	}      tmp = fold_build2 (MULT_EXPR, gfc_array_index_type,			 GFC_TYPE_ARRAY_LBOUND (type, n),			 GFC_TYPE_ARRAY_STRIDE (type, n));      offset = fold_build2 (MINUS_EXPR, gfc_array_index_type, offset, tmp);    }  offset = gfc_evaluate_now (offset, block);  GFC_TYPE_ARRAY_OFFSET (type) = offset;}/* Extend MAPPING so that it maps dummy argument SYM to the value stored   in SE.  The caller may still use se->expr and se->string_length after   calling this function.  */voidgfc_add_interface_mapping (gfc_interface_mapping * mapping,			   gfc_symbol * sym, gfc_se * se){  gfc_interface_sym_mapping *sm;  tree desc;  tree tmp;  tree value;  gfc_symbol *new_sym;  gfc_symtree *root;  gfc_symtree *new_symtree;  /* Create a new symbol to represent the actual argument.  */  new_sym = gfc_new_symbol (sym->name, NULL);  new_sym->ts = sym->ts;  new_sym->attr.referenced = 1;  new_sym->attr.dimension = sym->attr.dimension;  new_sym->attr.pointer = sym->attr.pointer;  new_sym->attr.flavor = sym->attr.flavor;  /* Create a fake symtree for it.  */  root = NULL;  new_symtree = gfc_new_symtree (&root, sym->name);  new_symtree->n.sym = new_sym;  gcc_assert (new_symtree == root);  /* Create a dummy->actual mapping.  */  sm = gfc_getmem (sizeof (*sm));  sm->next = mapping->syms;  sm->old = sym;  sm->new = new_symtree;  mapping->syms = sm;  /* Stabilize the argument's value.  */  se->expr = gfc_evaluate_now (se->expr, &se->pre);  if (sym->ts.type == BT_CHARACTER)    {      /* Create a copy of the dummy argument's length.  */      new_sym->ts.cl = gfc_get_interface_mapping_charlen (mapping, sym->ts.cl);      /* If the length is specified as "*", record the length that	 the caller is passing.  We should use the callee's length	 in all other cases.  */      if (!new_sym->ts.cl->length)	{	  se->string_length = gfc_evaluate_now (se->string_length, &se->pre);	  new_sym->ts.cl->backend_decl = se->string_length;	}    }  /* Use the passed value as-is if the argument is a function.  */  if (sym->attr.flavor == FL_PROCEDURE)    value = se->expr;  /* If the argument is either a string or a pointer to a string,     convert it to a boundless character type.  */  else if (!sym->attr.dimension && sym->ts.type == BT_CHARACTER)    {      tmp = gfc_get_character_type_len (sym->ts.kind, NULL);      tmp = build_pointer_type (tmp);      if (sym->attr.pointer)	tmp = build_pointer_type (tmp);      value = fold_convert (tmp, se->expr);      if (sym->attr.pointer)	value = gfc_build_indirect_ref (value);    }  /* If the argument is a scalar or a pointer to an array, dereference it.  */  else if (!sym->attr.dimension || sym->attr.pointer)    value = gfc_build_indirect_ref (se->expr);  /* If the argument is an array descriptor, use it to determine     information about the actual argument's shape.  */  else if (POINTER_TYPE_P (TREE_TYPE (se->expr))	   && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))    {      /* Get the actual argument's descriptor.  */      desc = gfc_build_indirect_ref (se->expr);      /* Create the replacement variable.  */      tmp = gfc_conv_descriptor_data_get (desc);      value = gfc_get_interface_mapping_array (&se->pre, sym, 0, tmp);      /* Use DESC to work out the upper bounds, strides and offset.  */      gfc_set_interface_mapping_bounds (&se->pre, TREE_TYPE (value), desc);    }  else    /* Otherwise we have a packed array.  */    value = gfc_get_interface_mapping_array (&se->pre, sym, 2, se->expr);  new_sym->backend_decl = value;}/* Called once all dummy argument mappings have been added to MAPPING,   but before the mapping is used to evaluate expressions.  Pre-evaluate   the length of each argument, adding any initialization code to PRE and   any finalization code to POST.  */voidgfc_finish_interface_mapping (gfc_interface_mapping * mapping,			      stmtblock_t * pre, stmtblock_t * post){  gfc_interface_sym_mapping *sym;  gfc_expr *expr;  gfc_se se;  for (sym = mapping->syms; sym; sym = sym->next)    if (sym->new->n.sym->ts.type == BT_CHARACTER	&& !sym->new->n.sym->ts.cl->backend_decl)      {	expr = sym->new->n.sym->ts.cl->length;	gfc_apply_interface_mapping_to_expr (mapping, expr);	gfc_init_se (&se, NULL);	gfc_conv_expr (&se, expr);	se.expr = gfc_evaluate_now (se.expr, &se.pre);	gfc_add_block_to_block (pre, &se.pre);	gfc_add_block_to_block (post, &se.post);	sym->new->n.sym->ts.cl->backend_decl = se.expr;      }}/* Like gfc_apply_interface_mapping_to_expr, but applied to   constructor C.  */

⌨️ 快捷键说明

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