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

📄 trans-intrinsic.c

📁 gcc-fortran,linux使用fortran的编译软件。很好用的。
💻 C
📖 第 1 页 / 共 5 页
字号:
  tmp = fold_build2 (TRUTH_XOR_EXPR, boolean_type_node, testa, testb);  se->expr = fold_build3 (COND_EXPR, type, tmp,			  build1 (NEGATE_EXPR, type, arg), arg);}/* Test for the presence of an optional argument.  */static voidgfc_conv_intrinsic_present (gfc_se * se, gfc_expr * expr){  gfc_expr *arg;  arg = expr->value.function.actual->expr;  gcc_assert (arg->expr_type == EXPR_VARIABLE);  se->expr = gfc_conv_expr_present (arg->symtree->n.sym);  se->expr = convert (gfc_typenode_for_spec (&expr->ts), se->expr);}/* Calculate the double precision product of two single precision values.  */static voidgfc_conv_intrinsic_dprod (gfc_se * se, gfc_expr * expr){  tree arg;  tree arg2;  tree type;  arg = gfc_conv_intrinsic_function_args (se, expr);  arg2 = TREE_VALUE (TREE_CHAIN (arg));  arg = TREE_VALUE (arg);  /* Convert the args to double precision before multiplying.  */  type = gfc_typenode_for_spec (&expr->ts);  arg = convert (type, arg);  arg2 = convert (type, arg2);  se->expr = build2 (MULT_EXPR, type, arg, arg2);}/* Return a length one character string containing an ascii character.  */static voidgfc_conv_intrinsic_char (gfc_se * se, gfc_expr * expr){  tree arg;  tree var;  tree type;  arg = gfc_conv_intrinsic_function_args (se, expr);  arg = TREE_VALUE (arg);  /* We currently don't support character types != 1.  */  gcc_assert (expr->ts.kind == 1);  type = gfc_character1_type_node;  var = gfc_create_var (type, "char");  arg = convert (type, arg);  gfc_add_modify_expr (&se->pre, var, arg);  se->expr = gfc_build_addr_expr (build_pointer_type (type), var);  se->string_length = integer_one_node;}static voidgfc_conv_intrinsic_ctime (gfc_se * se, gfc_expr * expr){  tree var;  tree len;  tree tmp;  tree arglist;  tree type;  tree cond;  tree gfc_int8_type_node = gfc_get_int_type (8);  type = build_pointer_type (gfc_character1_type_node);  var = gfc_create_var (type, "pstr");  len = gfc_create_var (gfc_int8_type_node, "len");  tmp = gfc_conv_intrinsic_function_args (se, expr);  arglist = gfc_chainon_list (NULL_TREE, gfc_build_addr_expr (NULL, var));  arglist = gfc_chainon_list (arglist, gfc_build_addr_expr (NULL, len));  arglist = chainon (arglist, tmp);  tmp = gfc_build_function_call (gfor_fndecl_ctime, arglist);  gfc_add_expr_to_block (&se->pre, tmp);  /* Free the temporary afterwards, if necessary.  */  cond = build2 (GT_EXPR, boolean_type_node, len,		 build_int_cst (TREE_TYPE (len), 0));  arglist = gfc_chainon_list (NULL_TREE, var);  tmp = gfc_build_function_call (gfor_fndecl_internal_free, arglist);  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());  gfc_add_expr_to_block (&se->post, tmp);  se->expr = var;  se->string_length = len;}static voidgfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr){  tree var;  tree len;  tree tmp;  tree arglist;  tree type;  tree cond;  tree gfc_int4_type_node = gfc_get_int_type (4);  type = build_pointer_type (gfc_character1_type_node);  var = gfc_create_var (type, "pstr");  len = gfc_create_var (gfc_int4_type_node, "len");  tmp = gfc_conv_intrinsic_function_args (se, expr);  arglist = gfc_chainon_list (NULL_TREE, gfc_build_addr_expr (NULL, var));  arglist = gfc_chainon_list (arglist, gfc_build_addr_expr (NULL, len));  arglist = chainon (arglist, tmp);  tmp = gfc_build_function_call (gfor_fndecl_fdate, arglist);  gfc_add_expr_to_block (&se->pre, tmp);  /* Free the temporary afterwards, if necessary.  */  cond = build2 (GT_EXPR, boolean_type_node, len,		 build_int_cst (TREE_TYPE (len), 0));  arglist = gfc_chainon_list (NULL_TREE, var);  tmp = gfc_build_function_call (gfor_fndecl_internal_free, arglist);  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());  gfc_add_expr_to_block (&se->post, tmp);  se->expr = var;  se->string_length = len;}/* Return a character string containing the tty name.  */static voidgfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr){  tree var;  tree len;  tree tmp;  tree arglist;  tree type;  tree cond;  tree gfc_int4_type_node = gfc_get_int_type (4);  type = build_pointer_type (gfc_character1_type_node);  var = gfc_create_var (type, "pstr");  len = gfc_create_var (gfc_int4_type_node, "len");  tmp = gfc_conv_intrinsic_function_args (se, expr);  arglist = gfc_chainon_list (NULL_TREE, gfc_build_addr_expr (NULL, var));  arglist = gfc_chainon_list (arglist, gfc_build_addr_expr (NULL, len));  arglist = chainon (arglist, tmp);  tmp = gfc_build_function_call (gfor_fndecl_ttynam, arglist);  gfc_add_expr_to_block (&se->pre, tmp);  /* Free the temporary afterwards, if necessary.  */  cond = build2 (GT_EXPR, boolean_type_node, len,		 build_int_cst (TREE_TYPE (len), 0));  arglist = gfc_chainon_list (NULL_TREE, var);  tmp = gfc_build_function_call (gfor_fndecl_internal_free, arglist);  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());  gfc_add_expr_to_block (&se->post, tmp);  se->expr = var;  se->string_length = len;}/* Get the minimum/maximum value of all the parameters.    minmax (a1, a2, a3, ...)    {      if (a2 .op. a1)        mvar = a2;      else        mvar = a1;      if (a3 .op. mvar)        mvar = a3;      ...      return mvar    } *//* TODO: Mismatching types can occur when specific names are used.   These should be handled during resolution.  */static voidgfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op){  tree limit;  tree tmp;  tree mvar;  tree val;  tree thencase;  tree elsecase;  tree arg;  tree type;  arg = gfc_conv_intrinsic_function_args (se, expr);  type = gfc_typenode_for_spec (&expr->ts);  limit = TREE_VALUE (arg);  if (TREE_TYPE (limit) != type)    limit = convert (type, limit);  /* Only evaluate the argument once.  */  if (TREE_CODE (limit) != VAR_DECL && !TREE_CONSTANT (limit))    limit = gfc_evaluate_now(limit, &se->pre);  mvar = gfc_create_var (type, "M");  elsecase = build2_v (MODIFY_EXPR, mvar, limit);  for (arg = TREE_CHAIN (arg); arg != NULL_TREE; arg = TREE_CHAIN (arg))    {      val = TREE_VALUE (arg);      if (TREE_TYPE (val) != type)	val = convert (type, val);      /* Only evaluate the argument once.  */      if (TREE_CODE (val) != VAR_DECL && !TREE_CONSTANT (val))        val = gfc_evaluate_now(val, &se->pre);      thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val));      tmp = build2 (op, boolean_type_node, val, limit);      tmp = build3_v (COND_EXPR, tmp, thencase, elsecase);      gfc_add_expr_to_block (&se->pre, tmp);      elsecase = build_empty_stmt ();      limit = mvar;    }  se->expr = mvar;}/* Create a symbol node for this intrinsic.  The symbol from the frontend   has the generic name.  */static gfc_symbol *gfc_get_symbol_for_expr (gfc_expr * expr){  gfc_symbol *sym;  /* TODO: Add symbols for intrinsic function to the global namespace.  */  gcc_assert (strlen (expr->value.function.name) <= GFC_MAX_SYMBOL_LEN - 5);  sym = gfc_new_symbol (expr->value.function.name, NULL);  sym->ts = expr->ts;  sym->attr.external = 1;  sym->attr.function = 1;  sym->attr.always_explicit = 1;  sym->attr.proc = PROC_INTRINSIC;  sym->attr.flavor = FL_PROCEDURE;  sym->result = sym;  if (expr->rank > 0)    {      sym->attr.dimension = 1;      sym->as = gfc_get_array_spec ();      sym->as->type = AS_ASSUMED_SHAPE;      sym->as->rank = expr->rank;    }  /* TODO: proper argument lists for external intrinsics.  */  return sym;}/* Generate a call to an external intrinsic function.  */static voidgfc_conv_intrinsic_funcall (gfc_se * se, gfc_expr * expr){  gfc_symbol *sym;  gcc_assert (!se->ss || se->ss->expr == expr);  if (se->ss)    gcc_assert (expr->rank > 0);  else    gcc_assert (expr->rank == 0);  sym = gfc_get_symbol_for_expr (expr);  gfc_conv_function_call (se, sym, expr->value.function.actual);  gfc_free (sym);}/* ANY and ALL intrinsics. ANY->op == NE_EXPR, ALL->op == EQ_EXPR.   Implemented as    any(a)    {      forall (i=...)        if (a[i] != 0)          return 1      end forall      return 0    }    all(a)    {      forall (i=...)        if (a[i] == 0)          return 0      end forall      return 1    } */static voidgfc_conv_intrinsic_anyall (gfc_se * se, gfc_expr * expr, int op){  tree resvar;  stmtblock_t block;  stmtblock_t body;  tree type;  tree tmp;  tree found;  gfc_loopinfo loop;  gfc_actual_arglist *actual;  gfc_ss *arrayss;  gfc_se arrayse;  tree exit_label;  if (se->ss)    {      gfc_conv_intrinsic_funcall (se, expr);      return;    }  actual = expr->value.function.actual;  type = gfc_typenode_for_spec (&expr->ts);  /* Initialize the result.  */  resvar = gfc_create_var (type, "test");  if (op == EQ_EXPR)    tmp = convert (type, boolean_true_node);  else    tmp = convert (type, boolean_false_node);  gfc_add_modify_expr (&se->pre, resvar, tmp);  /* Walk the arguments.  */  arrayss = gfc_walk_expr (actual->expr);  gcc_assert (arrayss != gfc_ss_terminator);  /* Initialize the scalarizer.  */  gfc_init_loopinfo (&loop);  exit_label = gfc_build_label_decl (NULL_TREE);  TREE_USED (exit_label) = 1;  gfc_add_ss_to_loop (&loop, arrayss);  /* Initialize the loop.  */  gfc_conv_ss_startstride (&loop);  gfc_conv_loop_setup (&loop);  gfc_mark_ss_chain_used (arrayss, 1);  /* Generate the loop body.  */  gfc_start_scalarized_body (&loop, &body);  /* If the condition matches then set the return value.  */  gfc_start_block (&block);  if (op == EQ_EXPR)    tmp = convert (type, boolean_false_node);  else    tmp = convert (type, boolean_true_node);  gfc_add_modify_expr (&block, resvar, tmp);  /* And break out of the loop.  */  tmp = build1_v (GOTO_EXPR, exit_label);  gfc_add_expr_to_block (&block, tmp);  found = gfc_finish_block (&block);  /* Check this element.  */  gfc_init_se (&arrayse, NULL);  gfc_copy_loopinfo_to_se (&arrayse, &loop);  arrayse.ss = arrayss;  gfc_conv_expr_val (&arrayse, actual->expr);  gfc_add_block_to_block (&body, &arrayse.pre);  tmp = build2 (op, boolean_type_node, arrayse.expr,		build_int_cst (TREE_TYPE (arrayse.expr), 0));  tmp = build3_v (COND_EXPR, tmp, found, build_empty_stmt ());  gfc_add_expr_to_block (&body, tmp);  gfc_add_block_to_block (&body, &arrayse.post);  gfc_trans_scalarizing_loops (&loop, &body);  /* Add the exit label.  */  tmp = build1_v (LABEL_EXPR, exit_label);  gfc_add_expr_to_block (&loop.pre, tmp);  gfc_add_block_to_block (&se->pre, &loop.pre);  gfc_add_block_to_block (&se->pre, &loop.post);  gfc_cleanup_loop (&loop);  se->expr = resvar;}/* COUNT(A) = Number of true elements in A.  */static voidgfc_conv_intrinsic_count (gfc_se * se, gfc_expr * expr){  tree resvar;  tree type;  stmtblock_t body;  tree tmp;  gfc_loopinfo loop;  gfc_actual_arglist *actual;  gfc_ss *arrayss;  gfc_se arrayse;  if (se->ss)    {      gfc_conv_intrinsic_funcall (se, expr);      return;    }  actual = expr->value.function.actual;  type = gfc_typenode_for_spec (&expr->ts);  /* Initialize the result.  */  resvar = gfc_create_var (type, "count");  gfc_add_modify_expr (&se->pre, resvar, build_int_cst (type, 0));  /* Walk the arguments.  */  arrayss = gfc_walk_expr (actual->expr);  gcc_assert (arrayss != gfc_ss_terminator);  /* Initialize the scalarizer.  */  gfc_init_loopinfo (&loop);  gfc_add_ss_to_loop (&loop, arrayss);  /* Initialize the loop.  */  gfc_conv_ss_startstride (&loop);  gfc_conv_loop_setup (&loop);  gfc_mark_ss_chain_used (arrayss, 1);  /* Generate the loop body.  */  gfc_start_scalarized_body (&loop, &body);  tmp = build2 (PLUS_EXPR, TREE_TYPE (resvar), resvar,		build_int_cst (TREE_TYPE (resvar), 1));  tmp = build2_v (MODIFY_EXPR, resvar, tmp);  gfc_init_se (&arrayse, NULL);  gfc_copy_loopinfo_to_se (&arrayse, &loop);  arrayse.ss = arrayss;  gfc_conv_expr_val (&arrayse, actual->expr);  tmp = build3_v (COND_EXPR, arrayse.expr, tmp, build_empty_stmt ());  gfc_add_block_to_block (&body, &arrayse.pre);  gfc_add_expr_to_block (&body, tmp);  gfc_add_block_to_block (&body, &arrayse.post);  gfc_trans_scalarizing_loops (&loop, &body);  gfc_add_block_to_block (&se->pre, &loop.pre);  gfc_add_block_to_block (&se->pre, &loop.post);  gfc_cleanup_loop (&loop);  se->expr = resvar;}/* Inline implementation of the sum and product intrinsics.  */static voidgfc_conv_intrinsic_arith (gfc_se * se, gfc_expr * expr, int op){  tree resvar;  tree type;  stmtblock_t body;  stmtblock_t block;  tree tmp;  gfc_loopinfo loop;  gfc_actual_arglist *actual;  gfc_ss *arrayss;  gfc_ss *maskss;  gfc_se arrayse;  gfc_se maskse;  gfc_expr *arrayexpr;  gfc_expr *maskexpr;  if (se->ss)    {      gfc_conv_intrinsic_funcall (se, expr);      return;    }  type = gfc_typenode_for_spec (&expr->ts);  /* Initialize the result.  */  resvar = gfc_create_var (type, "val");  if (op == PLUS_EXPR)

⌨️ 快捷键说明

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