コード例 #1
0
ファイル: typeck.c プロジェクト: AHelper/gcc
static tree
convert_ieee_real_to_integer (tree type, tree expr)
{
  tree result;
  expr = save_expr (expr);

  result = fold_build3 (COND_EXPR, type,
			fold_build2 (NE_EXPR, boolean_type_node, expr, expr),
			 convert (type, integer_zero_node),
			 convert_to_integer (type, expr));
  
  result = fold_build3 (COND_EXPR, type, 
			fold_build2 (LE_EXPR, boolean_type_node, expr, 
				     convert (TREE_TYPE (expr), 
					      TYPE_MIN_VALUE (type))),
			TYPE_MIN_VALUE (type),
			result);
  
  result = fold_build3 (COND_EXPR, type,
			fold_build2 (GE_EXPR, boolean_type_node, expr, 
				     convert (TREE_TYPE (expr), 
					      TYPE_MAX_VALUE (type))),
			TYPE_MAX_VALUE (type),
			result);

  return result;
}  
コード例 #2
0
/*
 *	Create a type of integers to be the TYPE_DOMAIN
 *	of an ARRAY_TYPE. MAXVAL should be the maximum
 *	value in the domain (one less than the length of
 *	the array).
 */
tree
build_index_type (tree maxval)
{
	register tree	itype = make_node (INTEGER_TYPE);

	TYPE_PRECISION (itype) = BITS_PER_WORD;
	TYPE_MIN_VALUE (itype) = build_int_2 (0, 0);
	TREE_TYPE (TYPE_MIN_VALUE (itype)) = sizetype;
	TYPE_MAX_VALUE (itype) = convert (sizetype, maxval);
	TYPE_MODE (itype) = SImode;
	TYPE_SIZE (itype) = TYPE_SIZE (sizetype);
	TYPE_SIZE_UNIT (itype) = TYPE_SIZE_UNIT (sizetype);
	TYPE_ALIGN (itype) = TYPE_ALIGN (sizetype);

	if (TREE_CODE (maxval) == INTEGER_CST)
	{
		int maxint = TREE_INT_CST_LOW (maxval);

		return (type_hash_canon (maxint > 0 ? maxint : - maxint, itype));
	}
	else
	{
		return (itype);
	}

}	/* end build_index_type */
コード例 #3
0
ファイル: lighthouse-tree.c プロジェクト: ctz/lighthouse
/* Returns true if the bound (higher for nonzero hi, otherwise lower)
 * of `cst' is not the bound implied by the type's precision and signedness. */
static bool integer_cst_interesting(tree cst, int hi)
{
    return true;
#if 0
    long long implicit_bound, explicit_bound;

    if (TYPE_UNSIGNED(cst))
        implicit_bound = (1 << TYPE_PRECISION(cst)) - 1;
    else
        implicit_bound = (1 << (TYPE_PRECISION(cst) - 1)) - 1;

    if (TYPE_UNSIGNED(cst) && TYPE_PRECISION(cst) / 8 == sizeof(implicit_bound))
        implicit_bound = (long long) -1;

    if (!hi)
    {
        if (TYPE_UNSIGNED(cst))
            implicit_bound = 0;
        else
            implicit_bound = -implicit_bound-1;
    }

    explicit_bound = (hi) ? double_int_to_ll(TREE_INT_CST(TYPE_MAX_VALUE(cst))) :
                     double_int_to_ll(TREE_INT_CST(TYPE_MIN_VALUE(cst)));

    return explicit_bound != implicit_bound;
#endif
}
コード例 #4
0
ファイル: c-ubsan.c プロジェクト: kleopatra999/gcc
tree
ubsan_instrument_division (location_t loc, tree op0, tree op1)
{
  tree t, tt;
  tree type = TREE_TYPE (op0);

  /* At this point both operands should have the same type,
     because they are already converted to RESULT_TYPE.
     Use TYPE_MAIN_VARIANT since typedefs can confuse us.  */
  gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
	      == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));

  /* TODO: REAL_TYPE is not supported yet.  */
  if (TREE_CODE (type) != INTEGER_TYPE)
    return NULL_TREE;

  t = fold_build2 (EQ_EXPR, boolean_type_node,
		    op1, build_int_cst (type, 0));

  /* We check INT_MIN / -1 only for signed types.  */
  if (!TYPE_UNSIGNED (type))
    {
      tree x;
      tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
			build_int_cst (type, -1));
      x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
		       TYPE_MIN_VALUE (type));
      x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
      t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
    }

  /* If the condition was folded to 0, no need to instrument
     this expression.  */
  if (integer_zerop (t))
    return NULL_TREE;

  /* In case we have a SAVE_EXPR in a conditional context, we need to
     make sure it gets evaluated before the condition.  */
  t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
  if (flag_sanitize_undefined_trap_on_error)
    tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
  else
    {
      tree data = ubsan_create_data ("__ubsan_overflow_data", &loc, NULL,
				     ubsan_type_descriptor (type, false),
				     NULL_TREE);
      data = build_fold_addr_expr_loc (loc, data);
      enum built_in_function bcode
	= flag_sanitize_recover
	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
      tt = builtin_decl_explicit (bcode);
      tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
				ubsan_encode_value (op1));
    }
  t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);

  return t;
}
コード例 #5
0
ファイル: trans.c プロジェクト: zxombie/aarch64-freebsd-gcc
tree
gfc_build_addr_expr (tree type, tree t)
{
  tree base_type = TREE_TYPE (t);
  tree natural_type;

  if (type && POINTER_TYPE_P (type)
      && TREE_CODE (base_type) == ARRAY_TYPE
      && TYPE_MAIN_VARIANT (TREE_TYPE (type))
	 == TYPE_MAIN_VARIANT (TREE_TYPE (base_type)))
    {
      tree min_val = size_zero_node;
      tree type_domain = TYPE_DOMAIN (base_type);
      if (type_domain && TYPE_MIN_VALUE (type_domain))
        min_val = TYPE_MIN_VALUE (type_domain);
      t = fold (build4_loc (input_location, ARRAY_REF, TREE_TYPE (type),
			    t, min_val, NULL_TREE, NULL_TREE));
      natural_type = type;
    }
  else
    natural_type = build_pointer_type (base_type);

  if (TREE_CODE (t) == INDIRECT_REF)
    {
      if (!type)
	type = natural_type;
      t = TREE_OPERAND (t, 0);
      natural_type = TREE_TYPE (t);
    }
  else
    {
      tree base = get_base_address (t);
      if (base && DECL_P (base))
        TREE_ADDRESSABLE (base) = 1;
      t = fold_build1_loc (input_location, ADDR_EXPR, natural_type, t);
    }

  if (type && natural_type != type)
    t = convert (type, t);

  return t;
}
コード例 #6
0
ファイル: tree-ssanames.c プロジェクト: codebruh/gcc
void
set_nonzero_bits (tree name, const wide_int_ref &mask)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  if (SSA_NAME_RANGE_INFO (name) == NULL)
    set_range_info (name, VR_RANGE,
		    TYPE_MIN_VALUE (TREE_TYPE (name)),
		    TYPE_MAX_VALUE (TREE_TYPE (name)));
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  ri->set_nonzero_bits (mask);
}
コード例 #7
0
ファイル: c-ubsan.c プロジェクト: hnaik/gcc
tree
ubsan_instrument_division (location_t loc, tree op0, tree op1)
{
    tree t, tt;
    tree type = TREE_TYPE (op0);

    /* At this point both operands should have the same type,
       because they are already converted to RESULT_TYPE.
       Use TYPE_MAIN_VARIANT since typedefs can confuse us.  */
    gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
                == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));

    /* TODO: REAL_TYPE is not supported yet.  */
    if (TREE_CODE (type) != INTEGER_TYPE)
        return NULL_TREE;

    /* If we *know* that the divisor is not -1 or 0, we don't have to
       instrument this expression.
       ??? We could use decl_constant_value to cover up more cases.  */
    if (TREE_CODE (op1) == INTEGER_CST
            && integer_nonzerop (op1)
            && !integer_minus_onep (op1))
        return NULL_TREE;

    t = fold_build2 (EQ_EXPR, boolean_type_node,
                     op1, build_int_cst (type, 0));

    /* We check INT_MIN / -1 only for signed types.  */
    if (!TYPE_UNSIGNED (type))
    {
        tree x;
        tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
                          build_int_cst (type, -1));
        x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
                         TYPE_MIN_VALUE (type));
        x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
        t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
    }

    /* In case we have a SAVE_EXPR in a conditional context, we need to
       make sure it gets evaluated before the condition.  */
    t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
    tree data = ubsan_create_data ("__ubsan_overflow_data",
                                   loc, ubsan_type_descriptor (type),
                                   NULL_TREE);
    data = build_fold_addr_expr_loc (loc, data);
    tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW);
    tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
                              ubsan_encode_value (op1));
    t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node);

    return t;
}
コード例 #8
0
ファイル: tree-ssanames.c プロジェクト: ds2dev/gcc
void
set_nonzero_bits (tree name, double_int mask)
{
  gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
  if (SSA_NAME_RANGE_INFO (name) == NULL)
    set_range_info (name, VR_RANGE,
		    tree_to_double_int (TYPE_MIN_VALUE (TREE_TYPE (name))),
		    tree_to_double_int (TYPE_MAX_VALUE (TREE_TYPE (name))));
  range_info_def *ri = SSA_NAME_RANGE_INFO (name);
  ri->nonzero_bits
    = mask & double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
}
コード例 #9
0
ファイル: tree-browser.c プロジェクト: 3F/gcc
void
browse_tree (tree begin)
{
  tree head;
  TB_CODE tbc = TB_UNUSED_COMMAND;
  ssize_t rd;
  char *input = NULL;
  long input_size = 0;

  fprintf (TB_OUT_FILE, "\nTree Browser\n");

#define TB_SET_HEAD(N) do {                                           \
  vec_safe_push (TB_history_stack, N);                                \
  head = N;                                                           \
  if (TB_verbose)                                                     \
    if (head)                                                         \
      {                                                               \
	print_generic_expr (TB_OUT_FILE, head, 0);                    \
	fprintf (TB_OUT_FILE, "\n");                                  \
      }                                                               \
} while (0)

  TB_SET_HEAD (begin);

  /* Store in a hashtable information about previous and upper statements.  */
  {
    TB_up_ht = new hash_table<tree_upper_hasher> (1023);
    TB_update_up (head);
  }

  while (24)
    {
      fprintf (TB_OUT_FILE, "TB> ");
      rd = TB_getline (&input, &input_size, TB_IN_FILE);

      if (rd == -1)
	/* EOF.  */
	goto ret;

      if (rd != 1)
	/* Get a new command.  Otherwise the user just pressed enter, and thus
	   she expects the last command to be reexecuted.  */
	tbc = TB_get_command (input);

      switch (tbc)
	{
	case TB_UPDATE_UP:
	  TB_update_up (head);
	  break;

	case TB_MAX:
	  if (head && (INTEGRAL_TYPE_P (head)
		       || TREE_CODE (head) == REAL_TYPE
		       || TREE_CODE (head) == FIXED_POINT_TYPE))
	    TB_SET_HEAD (TYPE_MAX_VALUE (head));
	  else
	    TB_WF;
	  break;

	case TB_MIN:
	  if (head && (INTEGRAL_TYPE_P (head)
		       || TREE_CODE (head) == REAL_TYPE
		       || TREE_CODE (head) == FIXED_POINT_TYPE))
	    TB_SET_HEAD (TYPE_MIN_VALUE (head));
	  else
	    TB_WF;
	  break;

	case TB_ELT:
	  if (head && TREE_CODE (head) == TREE_VEC)
	    {
	      /* This command takes another argument: the element number:
		 for example "elt 1".  */
	      TB_NIY;
	    }
	  else if (head && TREE_CODE (head) == VECTOR_CST)
	    {
	      /* This command takes another argument: the element number:
                 for example "elt 1".  */
              TB_NIY;
	    }
	  else
	    TB_WF;
	  break;

	case TB_VALUE:
	  if (head && TREE_CODE (head) == TREE_LIST)
	    TB_SET_HEAD (TREE_VALUE (head));
	  else
	    TB_WF;
	  break;

	case TB_PURPOSE:
	  if (head && TREE_CODE (head) == TREE_LIST)
	    TB_SET_HEAD (TREE_PURPOSE (head));
	  else
	    TB_WF;
	  break;

	case TB_IMAG:
	  if (head && TREE_CODE (head) == COMPLEX_CST)
	    TB_SET_HEAD (TREE_IMAGPART (head));
	  else
	    TB_WF;
	  break;

	case TB_REAL:
	  if (head && TREE_CODE (head) == COMPLEX_CST)
	    TB_SET_HEAD (TREE_REALPART (head));
	  else
	    TB_WF;
	  break;

	case TB_BLOCK:
	  if (head && TREE_CODE (head) == BIND_EXPR)
	    TB_SET_HEAD (TREE_OPERAND (head, 2));
	  else
	    TB_WF;
	  break;

	case TB_SUBBLOCKS:
	  if (head && TREE_CODE (head) == BLOCK)
	    TB_SET_HEAD (BLOCK_SUBBLOCKS (head));
	  else
	    TB_WF;
	  break;

	case TB_SUPERCONTEXT:
	  if (head && TREE_CODE (head) == BLOCK)
	    TB_SET_HEAD (BLOCK_SUPERCONTEXT (head));
	  else
	    TB_WF;
	  break;

	case TB_VARS:
	  if (head && TREE_CODE (head) == BLOCK)
	    TB_SET_HEAD (BLOCK_VARS (head));
	  else if (head && TREE_CODE (head) == BIND_EXPR)
	    TB_SET_HEAD (TREE_OPERAND (head, 0));
	  else
	    TB_WF;
	  break;

	case TB_REFERENCE_TO_THIS:
	  if (head && TYPE_P (head))
	    TB_SET_HEAD (TYPE_REFERENCE_TO (head));
	  else
	    TB_WF;
	  break;

	case TB_POINTER_TO_THIS:
	  if (head && TYPE_P (head))
	    TB_SET_HEAD (TYPE_POINTER_TO (head));
	  else
	    TB_WF;
	  break;

	case TB_BASETYPE:
	  if (head && TREE_CODE (head) == OFFSET_TYPE)
	    TB_SET_HEAD (TYPE_OFFSET_BASETYPE (head));
	  else
	    TB_WF;
	  break;

	case TB_ARG_TYPES:
	  if (head && (TREE_CODE (head) == FUNCTION_TYPE
		       || TREE_CODE (head) == METHOD_TYPE))
	    TB_SET_HEAD (TYPE_ARG_TYPES (head));
	  else
	    TB_WF;
	  break;

	case TB_METHOD_BASE_TYPE:
	  if (head && (TREE_CODE (head) == FUNCTION_TYPE
		       || TREE_CODE (head) == METHOD_TYPE)
	      && TYPE_METHOD_BASETYPE (head))
	    TB_SET_HEAD (TYPE_METHOD_BASETYPE (head));
	  else
	    TB_WF;
	  break;

	case TB_FIELDS:
	  if (head && (TREE_CODE (head) == RECORD_TYPE
		       || TREE_CODE (head) == UNION_TYPE
		       || TREE_CODE (head) == QUAL_UNION_TYPE))
	    TB_SET_HEAD (TYPE_FIELDS (head));
	  else
	    TB_WF;
	  break;

	case TB_DOMAIN:
	  if (head && TREE_CODE (head) == ARRAY_TYPE)
	    TB_SET_HEAD (TYPE_DOMAIN (head));
	  else
	    TB_WF;
	  break;

	case TB_VALUES:
	  if (head && TREE_CODE (head) == ENUMERAL_TYPE)
	    TB_SET_HEAD (TYPE_VALUES (head));
	  else
	    TB_WF;
	  break;

	case TB_ARG_TYPE:
	  if (head && TREE_CODE (head) == PARM_DECL)
	    TB_SET_HEAD (DECL_ARG_TYPE (head));
	  else
	    TB_WF;
	  break;

	case TB_INITIAL:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_INITIAL (head));
	  else
	    TB_WF;
	  break;

	case TB_RESULT:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_RESULT_FLD (head));
	  else
	    TB_WF;
	  break;

	case TB_ARGUMENTS:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_ARGUMENTS (head));
	  else
	    TB_WF;
	  break;

	case TB_ABSTRACT_ORIGIN:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_ABSTRACT_ORIGIN (head));
	  else if (head && TREE_CODE (head) == BLOCK)
	    TB_SET_HEAD (BLOCK_ABSTRACT_ORIGIN (head));
	  else
	    TB_WF;
	  break;

	case TB_ATTRIBUTES:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_ATTRIBUTES (head));
	  else if (head && TYPE_P (head))
	    TB_SET_HEAD (TYPE_ATTRIBUTES (head));
	  else
	    TB_WF;
	  break;

	case TB_CONTEXT:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_CONTEXT (head));
	  else if (head && TYPE_P (head)
		   && TYPE_CONTEXT (head))
	    TB_SET_HEAD (TYPE_CONTEXT (head));
	  else
	    TB_WF;
	  break;

	case TB_OFFSET:
	  if (head && TREE_CODE (head) == FIELD_DECL)
	    TB_SET_HEAD (DECL_FIELD_OFFSET (head));
	  else
	    TB_WF;
	  break;

	case TB_BIT_OFFSET:
	  if (head && TREE_CODE (head) == FIELD_DECL)
	    TB_SET_HEAD (DECL_FIELD_BIT_OFFSET (head));
	  else
	    TB_WF;
          break;

	case TB_UNIT_SIZE:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_SIZE_UNIT (head));
	  else if (head && TYPE_P (head))
	    TB_SET_HEAD (TYPE_SIZE_UNIT (head));
	  else
	    TB_WF;
	  break;

	case TB_SIZE:
	  if (head && DECL_P (head))
	    TB_SET_HEAD (DECL_SIZE (head));
	  else if (head && TYPE_P (head))
	    TB_SET_HEAD (TYPE_SIZE (head));
	  else
	    TB_WF;
	  break;

	case TB_TYPE:
	  if (head && TREE_TYPE (head))
	    TB_SET_HEAD (TREE_TYPE (head));
	  else
	    TB_WF;
	  break;

	case TB_DECL_SAVED_TREE:
	  if (head && TREE_CODE (head) == FUNCTION_DECL
	      && DECL_SAVED_TREE (head))
	    TB_SET_HEAD (DECL_SAVED_TREE (head));
	  else
	    TB_WF;
	  break;

	case TB_BODY:
	  if (head && TREE_CODE (head) == BIND_EXPR)
	    TB_SET_HEAD (TREE_OPERAND (head, 1));
	  else
	    TB_WF;
	  break;

	case TB_CHILD_0:
	  if (head && EXPR_P (head) && TREE_OPERAND (head, 0))
	    TB_SET_HEAD (TREE_OPERAND (head, 0));
	  else
	    TB_WF;
	  break;

	case TB_CHILD_1:
          if (head && EXPR_P (head) && TREE_OPERAND (head, 1))
	    TB_SET_HEAD (TREE_OPERAND (head, 1));
	  else
	    TB_WF;
          break;

	case TB_CHILD_2:
          if (head && EXPR_P (head) && TREE_OPERAND (head, 2))
	    TB_SET_HEAD (TREE_OPERAND (head, 2));
	  else
	    TB_WF;
	  break;

	case TB_CHILD_3:
	  if (head && EXPR_P (head) && TREE_OPERAND (head, 3))
	    TB_SET_HEAD (TREE_OPERAND (head, 3));
	  else
	    TB_WF;
          break;

	case TB_PRINT:
	  if (head)
	    debug_tree (head);
	  else
	    TB_WF;
	  break;

	case TB_PRETTY_PRINT:
	  if (head)
	    {
	      print_generic_stmt (TB_OUT_FILE, head, 0);
	      fprintf (TB_OUT_FILE, "\n");
	    }
	  else
	    TB_WF;
	  break;

	case TB_SEARCH_NAME:

	  break;

	case TB_SEARCH_CODE:
	  {
	    enum tree_code code;
	    char *arg_text;

	    arg_text = strchr (input, ' ');
	    if (arg_text == NULL)
	      {
		fprintf (TB_OUT_FILE, "First argument is missing.  This isn't a valid search command.  \n");
		break;
	      }
	    code = TB_get_tree_code (arg_text + 1);

	    /* Search in the subtree a node with the given code.  */
	    {
	      tree res;

	      res = walk_tree (&head, find_node_with_code, &code, NULL);
	      if (res == NULL_TREE)
		{
		  fprintf (TB_OUT_FILE, "There's no node with this code (reachable via the walk_tree function from this node).\n");
		}
	      else
		{
		  fprintf (TB_OUT_FILE, "Achoo!  I got this node in the tree.\n");
		  TB_SET_HEAD (res);
		}
	    }
	    break;
	  }

#define TB_MOVE_HEAD(FCT) do {       \
  if (head)                          \
    {                                \
      tree t;                        \
      t = FCT (head);                \
      if (t)                         \
        TB_SET_HEAD (t);             \
      else                           \
	TB_WF;                       \
    }                                \
  else                               \
    TB_WF;                           \
} while (0)

	case TB_FIRST:
	  TB_MOVE_HEAD (TB_first_in_bind);
          break;

        case TB_LAST:
          TB_MOVE_HEAD (TB_last_in_bind);
          break;

	case TB_UP:
	  TB_MOVE_HEAD (TB_up_expr);
	  break;

	case TB_PREV:
	  TB_MOVE_HEAD (TB_prev_expr);
	  break;

	case TB_NEXT:
	  TB_MOVE_HEAD (TB_next_expr);
	  break;

	case TB_HPREV:
	  /* This command is a little bit special, since it deals with history
	     stack.  For this reason it should keep the "head = ..." statement
	     and not use TB_MOVE_HEAD.  */
	  if (head)
	    {
	      tree t;
	      t = TB_history_prev ();
	      if (t)
		{
		  head = t;
		  if (TB_verbose)
		    {
		      print_generic_expr (TB_OUT_FILE, head, 0);
		      fprintf (TB_OUT_FILE, "\n");
		    }
		}
	      else
		TB_WF;
	    }
	  else
	    TB_WF;
	  break;

	case TB_CHAIN:
	  /* Don't go further if it's the last node in this chain.  */
	  if (head && TREE_CODE (head) == BLOCK)
	    TB_SET_HEAD (BLOCK_CHAIN (head));
	  else if (head && TREE_CHAIN (head))
	    TB_SET_HEAD (TREE_CHAIN (head));
	  else
	    TB_WF;
	  break;

	case TB_FUN:
	  /* Go up to the current function declaration.  */
	  TB_SET_HEAD (current_function_decl);
	  fprintf (TB_OUT_FILE, "Current function declaration.\n");
	  break;

	case TB_HELP:
	  /* Display a help message.  */
	  {
	    int i;
	    fprintf (TB_OUT_FILE, "Possible commands are:\n\n");
	    for (i = 0; i < TB_UNUSED_COMMAND; i++)
	      {
		fprintf (TB_OUT_FILE, "%20s  -  %s\n", TB_COMMAND_TEXT (i), TB_COMMAND_HELP (i));
	      }
	  }
	  break;

	case TB_VERBOSE:
	  if (TB_verbose == 0)
	    {
	      TB_verbose = 1;
	      fprintf (TB_OUT_FILE, "Verbose on.\n");
	    }
	  else
	    {
	      TB_verbose = 0;
	      fprintf (TB_OUT_FILE, "Verbose off.\n");
	    }
	  break;

	case TB_EXIT:
	case TB_QUIT:
	  /* Just exit from this function.  */
	  goto ret;

	default:
	  TB_NIY;
	}
    }

 ret:;
  delete TB_up_ht;
  TB_up_ht = NULL;
  return;
}
コード例 #10
0
ファイル: cp-array-notation.c プロジェクト: chinabin/gcc-tiny
static tree
expand_sec_reduce_builtin (tree an_builtin_fn, tree *new_var)
{
  tree new_var_type = NULL_TREE, func_parm, new_yes_expr, new_no_expr;
  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
  tree new_yes_list, new_cond_expr, new_expr = NULL_TREE; 
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree  body, an_init, loop_with_init = alloc_stmt_list ();
  tree array_op0, comp_node = NULL_TREE;
  tree call_fn = NULL_TREE, identity_value = NULL_TREE;
  tree init = NULL_TREE, cond_init = NULL_TREE;
  enum tree_code code = NOP_EXPR;
  location_t location = UNKNOWN_LOCATION;
  vec<vec<an_parts> > an_info = vNULL;
  auto_vec<an_loop_parts> an_loop_info;
  enum built_in_function an_type =
    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
  vec <tree, va_gc> *func_args;
  
  if (an_type == BUILT_IN_NONE)
    return NULL_TREE;

  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE
      && an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
  else
    {
      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);

      /* We need to do this because we are "faking" the builtin function types,
	 so the compiler does a bunch of typecasts and this will get rid of
	 all that!  */
      STRIP_NOPS (call_fn);
      if (TREE_CODE (call_fn) != OVERLOAD
	  && TREE_CODE (call_fn) != FUNCTION_DECL)
	call_fn = TREE_OPERAND (call_fn, 0);
      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
      STRIP_NOPS (identity_value);
    }
  STRIP_NOPS (func_parm);
  
  location = EXPR_LOCATION (an_builtin_fn);
  
  /* Note about using find_rank (): If find_rank returns false, then it must
     have already reported an error, thus we just return an error_mark_node
     without any doing any error emission.  */  
  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
      return error_mark_node;
  if (rank == 0)
    {
      error_at (location, "Invalid builtin arguments");
      return error_mark_node;
    }
  else if (rank > 1 
	   && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
    { 
      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot "
		"have arrays with dimension greater than 1");
      return error_mark_node;
    }
  
  extract_array_notation_exprs (func_parm, true, &array_list);
  list_size = vec_safe_length (array_list);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      new_var_type = boolean_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_type = size_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      if (call_fn && identity_value)
	new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_var_type = NULL_TREE;
      break;
    default:
      gcc_unreachable ();
    }
    
  if (new_var_type && TREE_CODE (new_var_type) == ARRAY_TYPE)
    new_var_type = TREE_TYPE (new_var_type);
  an_loop_info.safe_grow_cleared (rank);

  an_init = push_stmt_list ();

  /* Assign the array notation components to variable so that they can satisfy
     the exec-once rule.  */
  for (ii = 0; ii < list_size; ii++)
    if (TREE_CODE ((*array_list)[ii]) == ARRAY_NOTATION_REF)
      {
	tree anode = (*array_list)[ii];
	make_triplet_val_inv (&ARRAY_NOTATION_START (anode));
	make_triplet_val_inv (&ARRAY_NOTATION_LENGTH (anode));
	make_triplet_val_inv (&ARRAY_NOTATION_STRIDE (anode));
      }
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  for (ii = 0; ii < rank; ii++)
    {
      tree typ = ptrdiff_type_node;

      /* In this place, we are using get_temp_regvar instead of 
	 create_temporary_var if an_type is SEC_REDUCE_MAX/MIN_IND because
	 the array_ind_value depends on this value being initalized to 0.  */
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	  || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
	an_loop_info[ii].var = get_temp_regvar (typ, build_zero_cst (typ));
      else
	{
	  an_loop_info[ii].var = create_temporary_var (typ);
	  add_decl_expr (an_loop_info[ii].var);
	}
      an_loop_info[ii].ind_init = 
	build_x_modify_expr (location, an_loop_info[ii].var, INIT_EXPR,
			     build_zero_cst (typ), tf_warning_or_error);
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				      list_size, rank);
  replace_array_notations (&func_parm, true, array_list, array_operand);
  
  if (!TREE_TYPE (func_parm))      
    TREE_TYPE (func_parm) = TREE_TYPE ((*array_list)[0]);
  
  create_cmp_incr (location, &an_loop_info, rank, an_info, tf_warning_or_error);
  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND) 
    array_ind_value = get_temp_regvar (TREE_TYPE (func_parm), func_parm);

  array_op0 = (*array_operand)[0];
  if (INDIRECT_REF_P (array_op0))
    array_op0 = TREE_OPERAND (array_op0, 0);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
      code = PLUS_EXPR;
      init = build_zero_cst (new_var_type);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
      code = MULT_EXPR;
      init = build_one_cst (new_var_type);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO) ? EQ_EXPR
	: NE_EXPR);
      init = build_zero_cst (new_var_type);
      cond_init = build_one_cst (new_var_type);
      comp_node = build_zero_cst (TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      code = ((an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO) ? NE_EXPR
	: EQ_EXPR);
      init = build_one_cst (new_var_type);
      cond_init = build_zero_cst (new_var_type);
      comp_node = build_zero_cst (TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
      code = MAX_EXPR;
      init = (TYPE_MIN_VALUE (new_var_type) ? TYPE_MIN_VALUE (new_var_type)
	: func_parm);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      code = MIN_EXPR;
      init = (TYPE_MAX_VALUE (new_var_type) ? TYPE_MAX_VALUE (new_var_type)
	: func_parm);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
      code = (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND ? LE_EXPR
	: GE_EXPR);
      init = an_loop_info[0].var;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      init = identity_value;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      init = NULL_TREE;
      break;
    default:
      gcc_unreachable ();
    }

  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    *new_var = get_temp_regvar (new_var_type, init);
  else
    *new_var = NULL_TREE;

  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:      
      new_expr = build_x_modify_expr (location, *new_var, code, func_parm,
				      tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      /* In all these cases, assume the false case is true and as soon as
	 we find a true case,  set the true flag on and latch it in.  */
      new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
					  cond_init, tf_warning_or_error);
      new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
					 *new_var, tf_warning_or_error);
      new_cond_expr = build_x_binary_op
	(location, code, func_parm, TREE_CODE (func_parm), comp_node,
	 TREE_CODE (comp_node), NULL, tf_warning_or_error);
      new_expr = build_x_conditional_expr (location, new_cond_expr,
					   new_yes_expr, new_no_expr,
					   tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_cond_expr = build_x_binary_op
	(location, code, *new_var, TREE_CODE (*new_var), func_parm,
	 TREE_CODE (func_parm), NULL, tf_warning_or_error);
      new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, func_parm,
				      tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_yes_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
					  func_parm, tf_warning_or_error);
      new_no_expr = build_x_modify_expr (location, array_ind_value, NOP_EXPR,
					 array_ind_value, tf_warning_or_error);
      if (list_size > 1)
	new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
					   an_loop_info[0].var,
					   tf_warning_or_error);
      else
	new_yes_ind = build_x_modify_expr (location, *new_var, NOP_EXPR,
					   TREE_OPERAND (array_op0, 1),
					   tf_warning_or_error);
      new_no_ind = build_x_modify_expr (location, *new_var, NOP_EXPR, *new_var,
					tf_warning_or_error);
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);

      new_cond_expr = build_x_binary_op (location, code, array_ind_value,
					 TREE_CODE (array_ind_value), func_parm,
					 TREE_CODE (func_parm), NULL,
					 tf_warning_or_error);
      new_expr = build_x_conditional_expr (location, new_cond_expr,
					   new_yes_list, new_no_list,
					   tf_warning_or_error);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      func_args = make_tree_vector ();
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
	vec_safe_push (func_args, *new_var);
      else
	vec_safe_push (func_args, identity_value);
      vec_safe_push (func_args, func_parm);

      new_expr = finish_call_expr (call_fn, &func_args, false, true,
				   tf_warning_or_error);
      if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE)
	new_expr = build_x_modify_expr (location, *new_var, NOP_EXPR, new_expr,
					tf_warning_or_error);
      release_tree_vector (func_args);
      break;
    default:
      gcc_unreachable ();
    }
  an_init = pop_stmt_list (an_init);
  append_to_statement_list (an_init, &loop_with_init);
  body = new_expr;

  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      create_an_loop (an_loop_info[ii].ind_init, an_loop_info[ii].cmp,
		      an_loop_info[ii].incr, body);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list (body, &loop_with_init);

  release_vec_vec (an_info);

  return loop_with_init;
}
コード例 #11
0
ファイル: sdbout.c プロジェクト: BoxianLai/moxiedev
static int
plain_type_1 (tree type, int level)
{
  if (type == 0)
    type = void_type_node;
  else if (type == error_mark_node)
    type = integer_type_node;
  else
    type = TYPE_MAIN_VARIANT (type);

  switch (TREE_CODE (type))
    {
    case VOID_TYPE:
    case NULLPTR_TYPE:
      return T_VOID;
    case BOOLEAN_TYPE:
    case INTEGER_TYPE:
      {
	int size = int_size_in_bytes (type) * BITS_PER_UNIT;

	/* Carefully distinguish all the standard types of C,
	   without messing up if the language is not C.
	   Note that we check only for the names that contain spaces;
	   other names might occur by coincidence in other languages.  */
	if (TYPE_NAME (type) != 0
	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
	    && DECL_NAME (TYPE_NAME (type)) != 0
	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
	  {
	    const char *const name
	      = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));

	    if (!strcmp (name, "char"))
	      return T_CHAR;
	    if (!strcmp (name, "unsigned char"))
	      return T_UCHAR;
	    if (!strcmp (name, "signed char"))
	      return T_CHAR;
	    if (!strcmp (name, "int"))
	      return T_INT;
	    if (!strcmp (name, "unsigned int"))
	      return T_UINT;
	    if (!strcmp (name, "short int"))
	      return T_SHORT;
	    if (!strcmp (name, "short unsigned int"))
	      return T_USHORT;
	    if (!strcmp (name, "long int"))
	      return T_LONG;
	    if (!strcmp (name, "long unsigned int"))
	      return T_ULONG;
	  }

	if (size == INT_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_UINT : T_INT);
	if (size == CHAR_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
	if (size == SHORT_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_USHORT : T_SHORT);
	if (size == LONG_TYPE_SIZE)
	  return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG);
	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
	  return (TYPE_UNSIGNED (type) ? T_ULONG : T_LONG);
	return 0;
      }

    case REAL_TYPE:
      {
	int precision = TYPE_PRECISION (type);
	if (precision == FLOAT_TYPE_SIZE)
	  return T_FLOAT;
	if (precision == DOUBLE_TYPE_SIZE)
	  return T_DOUBLE;
#ifdef EXTENDED_SDB_BASIC_TYPES
	if (precision == LONG_DOUBLE_TYPE_SIZE)
	  return T_LNGDBL;
#else
	if (precision == LONG_DOUBLE_TYPE_SIZE)
	  return T_DOUBLE;	/* better than nothing */
#endif
	return 0;
      }

    case ARRAY_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	if (sdb_n_dims < SDB_MAX_DIM)
	  sdb_dims[sdb_n_dims++]
	    = (TYPE_DOMAIN (type)
	       && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
	       && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
	       && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
	       ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
		  - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1)
	       : 0);

	return PUSH_DERIVED_LEVEL (DT_ARY, m);
      }

    case RECORD_TYPE:
    case UNION_TYPE:
    case QUAL_UNION_TYPE:
    case ENUMERAL_TYPE:
      {
	const char *tag;
#ifdef SDB_ALLOW_FORWARD_REFERENCES
	sdbout_record_type_name (type);
#endif
#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
#ifdef SDB_ALLOW_FORWARD_REFERENCES
	    || TYPE_MODE (type) != VOIDmode
#endif
	    )
#endif
	  {
	    /* Output the referenced structure tag name
	       only if the .def has already been finished.
	       At least on 386, the Unix assembler
	       cannot handle forward references to tags.  */
	    /* But the 88100, it requires them, sigh...  */
	    /* And the MIPS requires unknown refs as well...  */
	    tag = KNOWN_TYPE_TAG (type);
	    PUT_SDB_TAG (tag);
	    /* These 3 lines used to follow the close brace.
	       However, a size of 0 without a tag implies a tag of 0,
	       so if we don't know a tag, we can't mention the size.  */
	    sdb_type_size = int_size_in_bytes (type);
	    if (sdb_type_size < 0)
	      sdb_type_size = 0;
	  }
	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
		: T_ENUM);
      }
    case POINTER_TYPE:
    case REFERENCE_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	return PUSH_DERIVED_LEVEL (DT_PTR, m);
      }
    case FUNCTION_TYPE:
    case METHOD_TYPE:
      {
	int m;
	if (level >= 6)
	  return T_VOID;
	else
	  m = plain_type_1 (TREE_TYPE (type), level+1);
	return PUSH_DERIVED_LEVEL (DT_FCN, m);
      }
    default:
      return 0;
    }
}
コード例 #12
0
ファイル: c-array-notation.c プロジェクト: AHelper/gcc
static tree
fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
{
  tree new_var_type = NULL_TREE, func_parm, new_expr, new_yes_expr, new_no_expr;
  tree array_ind_value = NULL_TREE, new_no_ind, new_yes_ind, new_no_list;
  tree new_yes_list, new_cond_expr, new_var_init = NULL_TREE;
  tree new_exp_init = NULL_TREE;
  vec<tree, va_gc> *array_list = NULL, *array_operand = NULL;
  size_t list_size = 0, rank = 0, ii = 0;
  tree loop_init, array_op0;
  tree identity_value = NULL_TREE, call_fn = NULL_TREE, new_call_expr, body;
  location_t location = UNKNOWN_LOCATION;
  tree loop_with_init = alloc_stmt_list ();
  vec<vec<an_parts> > an_info = vNULL;
  vec<an_loop_parts> an_loop_info = vNULL;
  enum built_in_function an_type =
    is_cilkplus_reduce_builtin (CALL_EXPR_FN (an_builtin_fn));
  if (an_type == BUILT_IN_NONE)
    return NULL_TREE;

  /* Builtin call should contain at least one argument.  */
  if (call_expr_nargs (an_builtin_fn) == 0)
    {
      error_at (EXPR_LOCATION (an_builtin_fn), "Invalid builtin arguments");
      return error_mark_node;
    }

  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    {
      call_fn = CALL_EXPR_ARG (an_builtin_fn, 2);
      if (TREE_CODE (call_fn) == ADDR_EXPR)
	call_fn = TREE_OPERAND (call_fn, 0);
      identity_value = CALL_EXPR_ARG (an_builtin_fn, 0);
      func_parm = CALL_EXPR_ARG (an_builtin_fn, 1);
    }
  else
    func_parm = CALL_EXPR_ARG (an_builtin_fn, 0);
  
  /* Fully fold any EXCESSIVE_PRECISION EXPR that can occur in the function
     parameter.  */
  func_parm = c_fully_fold (func_parm, false, NULL);
  if (func_parm == error_mark_node)
    return error_mark_node;
  
  location = EXPR_LOCATION (an_builtin_fn);
  
  if (!find_rank (location, an_builtin_fn, an_builtin_fn, true, &rank))
    return error_mark_node;
 
  if (rank == 0)
    {
      error_at (location, "Invalid builtin arguments");
      return error_mark_node;
    }
  else if (rank > 1 
	   && (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
	       || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND))
    {
      error_at (location, "__sec_reduce_min_ind or __sec_reduce_max_ind cannot"
		" have arrays with dimension greater than 1");
      return error_mark_node;
    }
  
  extract_array_notation_exprs (func_parm, true, &array_list);
  list_size = vec_safe_length (array_list);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      new_var_type = integer_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_type = integer_type_node;
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      if (call_fn && identity_value) 
	new_var_type = TREE_TYPE ((*array_list)[0]);
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_var_type = NULL_TREE;
      break;
    default:
      gcc_unreachable (); 
    }

  an_loop_info.safe_grow_cleared (rank);
  cilkplus_extract_an_triplets (array_list, list_size, rank, &an_info);
  loop_init = alloc_stmt_list ();

  for (ii = 0; ii < rank; ii++)
    {
      an_loop_info[ii].var = create_tmp_var (integer_type_node);
      an_loop_info[ii].ind_init =
	build_modify_expr (location, an_loop_info[ii].var,
			   TREE_TYPE (an_loop_info[ii].var), NOP_EXPR,
			   location,
			   build_int_cst (TREE_TYPE (an_loop_info[ii].var), 0),
			   TREE_TYPE (an_loop_info[ii].var));	
    }
  array_operand = create_array_refs (location, an_info, an_loop_info,
				     list_size, rank);
  replace_array_notations (&func_parm, true, array_list, array_operand);

  create_cmp_incr (location, &an_loop_info, rank, an_info);
  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    {
      *new_var = build_decl (location, VAR_DECL, NULL_TREE, new_var_type);
      gcc_assert (*new_var && *new_var != error_mark_node);
    }
  else
    *new_var = NULL_TREE;
  
  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
    array_ind_value = build_decl (location, VAR_DECL, NULL_TREE, 
				  TREE_TYPE (func_parm));
  array_op0 = (*array_operand)[0];
  if (TREE_CODE (array_op0) == INDIRECT_REF)
    array_op0 = TREE_OPERAND (array_op0, 0);
  switch (an_type)
    {
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ADD:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), PLUS_EXPR,
	 location, func_parm, TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUL:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), MULT_EXPR,
	 location, func_parm, TREE_TYPE (func_parm));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_ZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      /* Initially you assume everything is zero, now if we find a case where 
	 it is NOT true, then we set the result to false. Otherwise 
	 we just keep the previous value.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (TREE_TYPE (*new_var)),
	 TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ALL_NONZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      /* Initially you assume everything is non-zero, now if we find a case
	 where it is NOT true, then we set the result to false.  Otherwise
	 we just keep the previous value.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (TREE_TYPE (*new_var)),
	 TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_ZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      /* Initially we assume there are NO zeros in the list. When we find 
	 a non-zero, we keep the previous value.  If we find a zero, we 
	 set the value to true.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (EQ_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_ANY_NONZERO:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      /* Initially we assume there are NO non-zeros in the list. When we find 
	 a zero, we keep the previous value.  If we find a non-zero, we set 
	 the value to true.  */
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_one_cst (new_var_type), new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_cond_expr = build2 (NE_EXPR, TREE_TYPE (func_parm), func_parm,
			      build_zero_cst (TREE_TYPE (func_parm)));
      new_expr = build_conditional_expr
	(location, new_cond_expr, false, new_yes_expr,
	 TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));   
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX:
      if (TYPE_MIN_VALUE (new_var_type))
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, TYPE_MIN_VALUE (new_var_type), new_var_type);
      else
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, func_parm, new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, func_parm, TREE_TYPE (*new_var));
      new_expr = build_conditional_expr
	(location,
	 build2 (LT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN:
      if (TYPE_MAX_VALUE (new_var_type))
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, TYPE_MAX_VALUE (new_var_type), new_var_type);
      else
	new_var_init = build_modify_expr
	  (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	   location, func_parm, new_var_type);
      new_no_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_yes_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, func_parm, TREE_TYPE (*new_var));
      new_expr = build_conditional_expr
	(location,
	 build2 (GT_EXPR, TREE_TYPE (*new_var), *new_var, func_parm), false,
	 new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_exp_init = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
      new_no_ind = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR,
	 location, array_ind_value, TREE_TYPE (array_ind_value));
      if (list_size > 1)
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_TYPE ((*array_operand)[0]));
	}
      else
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, TREE_OPERAND (array_op0, 1),
	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_OPERAND (array_op0, 1));
	}
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);
 
      new_expr = build_conditional_expr
	(location,
	 build2 (LE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
		 func_parm),
	 false,
	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, build_zero_cst (new_var_type), new_var_type);
      new_exp_init = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR, location, func_parm, TREE_TYPE (func_parm));
      new_no_ind = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, *new_var, TREE_TYPE (*new_var));
      new_no_expr = build_modify_expr
	(location, array_ind_value, TREE_TYPE (array_ind_value),
	 NOP_EXPR,
	 location, array_ind_value, TREE_TYPE (array_ind_value));
      if (list_size > 1)
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, an_loop_info[0].var, TREE_TYPE (an_loop_info[0].var));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_TYPE (array_op0));
	}
      else
	{
	  new_yes_ind = build_modify_expr
	    (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	     location, TREE_OPERAND (array_op0, 1),
	     TREE_TYPE (TREE_OPERAND (array_op0, 1)));
	  new_yes_expr = build_modify_expr
	    (location, array_ind_value, TREE_TYPE (array_ind_value),
	     NOP_EXPR,
	     location, func_parm, TREE_OPERAND (array_op0, 1));
	}
      new_yes_list = alloc_stmt_list ();
      append_to_statement_list (new_yes_ind, &new_yes_list);
      append_to_statement_list (new_yes_expr, &new_yes_list);

      new_no_list = alloc_stmt_list ();
      append_to_statement_list (new_no_ind, &new_no_list);
      append_to_statement_list (new_no_expr, &new_no_list);
 
      new_expr = build_conditional_expr
	(location,
	 build2 (GE_EXPR, TREE_TYPE (array_ind_value), array_ind_value,
		 func_parm),
	 false,
	 new_yes_list, TREE_TYPE (*new_var), new_no_list, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE:
      new_var_init = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, identity_value, new_var_type);
      new_call_expr = build_call_expr (call_fn, 2, *new_var, func_parm);
      new_expr = build_modify_expr
	(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
	 location, new_call_expr, TREE_TYPE (*new_var));
      break;
    case BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING:
      new_expr = build_call_expr (call_fn, 2, identity_value, func_parm);
      break;
    default:
      gcc_unreachable ();
      break;
    }

  for (ii = 0; ii < rank; ii++)
    append_to_statement_list (an_loop_info[ii].ind_init, &loop_init);

  if (an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MAX_IND
      || an_type == BUILT_IN_CILKPLUS_SEC_REDUCE_MIN_IND)
    append_to_statement_list (new_exp_init, &loop_init);
  if (an_type != BUILT_IN_CILKPLUS_SEC_REDUCE_MUTATING)
    append_to_statement_list (new_var_init, &loop_init);

  append_to_statement_list_force (loop_init, &loop_with_init);
  body = new_expr;
  for (ii = 0; ii < rank; ii++)
    {
      tree new_loop = push_stmt_list ();
      c_finish_loop (location, an_loop_info[ii].cmp, an_loop_info[ii].incr,
		     body, NULL_TREE, NULL_TREE, true);
      body = pop_stmt_list (new_loop);
    }
  append_to_statement_list_force (body, &loop_with_init);

  an_info.release ();
  an_loop_info.release ();
  
  return loop_with_init;
}
コード例 #13
0
gcc_integer_type_get_min_value (gcc_integer_type node)
{
    return gcc_private_make_integer_constant (TYPE_MIN_VALUE (node.inner));
}
コード例 #14
0
ファイル: print-tree.c プロジェクト: RajibTheKing/gcc
void
print_node (FILE *file, const char *prefix, tree node, int indent)
{
    int hash;
    struct bucket *b;
    machine_mode mode;
    enum tree_code_class tclass;
    int len;
    int i;
    expanded_location xloc;
    enum tree_code code;

    if (node == 0)
        return;

    code = TREE_CODE (node);
    tclass = TREE_CODE_CLASS (code);

    /* Don't get too deep in nesting.  If the user wants to see deeper,
       it is easy to use the address of a lowest-level node
       as an argument in another call to debug_tree.  */

    if (indent > 24)
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    if (indent > 8 && (tclass == tcc_type || tclass == tcc_declaration))
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    /* It is unsafe to look at any other fields of an ERROR_MARK node.  */
    if (code == ERROR_MARK)
    {
        print_node_brief (file, prefix, node, indent);
        return;
    }

    /* Allow this function to be called if the table is not there.  */
    if (table)
    {
        hash = ((uintptr_t) node) % HASH_SIZE;

        /* If node is in the table, just mention its address.  */
        for (b = table[hash]; b; b = b->next)
            if (b->node == node)
            {
                print_node_brief (file, prefix, node, indent);
                return;
            }

        /* Add this node to the table.  */
        b = XNEW (struct bucket);
        b->node = node;
        b->next = table[hash];
        table[hash] = b;
    }

    /* Indent to the specified column, since this is the long form.  */
    indent_to (file, indent);

    /* Print the slot this node is in, and its code, and address.  */
    fprintf (file, "%s <%s", prefix, get_tree_code_name (code));
    dump_addr (file, " ", node);

    /* Print the name, if any.  */
    if (tclass == tcc_declaration)
    {
        if (DECL_NAME (node))
            fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node)));
        else if (code == LABEL_DECL
                 && LABEL_DECL_UID (node) != -1)
        {
            if (dump_flags & TDF_NOUID)
                fprintf (file, " L.xxxx");
            else
                fprintf (file, " L.%d", (int) LABEL_DECL_UID (node));
        }
        else
        {
            if (dump_flags & TDF_NOUID)
                fprintf (file, " %c.xxxx", code == CONST_DECL ? 'C' : 'D');
            else
                fprintf (file, " %c.%u", code == CONST_DECL ? 'C' : 'D',
                         DECL_UID (node));
        }
    }
    else if (tclass == tcc_type)
    {
        if (TYPE_NAME (node))
        {
            if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
                fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node)));
            else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
                     && DECL_NAME (TYPE_NAME (node)))
                fprintf (file, " %s",
                         IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node))));
        }
    }
    if (code == IDENTIFIER_NODE)
        fprintf (file, " %s", IDENTIFIER_POINTER (node));

    if (code == INTEGER_CST)
    {
        if (indent <= 4)
            print_node_brief (file, "type", TREE_TYPE (node), indent + 4);
    }
    else if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
    {
        print_node (file, "type", TREE_TYPE (node), indent + 4);
        if (TREE_TYPE (node))
            indent_to (file, indent + 3);
    }

    if (!TYPE_P (node) && TREE_SIDE_EFFECTS (node))
        fputs (" side-effects", file);

    if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node))
        fputs (" readonly", file);
    if (TYPE_P (node) && TYPE_ATOMIC (node))
        fputs (" atomic", file);
    if (!TYPE_P (node) && TREE_CONSTANT (node))
        fputs (" constant", file);
    else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node))
        fputs (" sizes-gimplified", file);

    if (TYPE_P (node) && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
        fprintf (file, " address-space-%d", TYPE_ADDR_SPACE (node));

    if (TREE_ADDRESSABLE (node))
        fputs (" addressable", file);
    if (TREE_THIS_VOLATILE (node))
        fputs (" volatile", file);
    if (TREE_ASM_WRITTEN (node))
        fputs (" asm_written", file);
    if (TREE_USED (node))
        fputs (" used", file);
    if (TREE_NOTHROW (node))
        fputs (" nothrow", file);
    if (TREE_PUBLIC (node))
        fputs (" public", file);
    if (TREE_PRIVATE (node))
        fputs (" private", file);
    if (TREE_PROTECTED (node))
        fputs (" protected", file);
    if (TREE_STATIC (node))
        fputs (code == CALL_EXPR ? " must-tail-call" : " static", file);
    if (TREE_DEPRECATED (node))
        fputs (" deprecated", file);
    if (TREE_VISITED (node))
        fputs (" visited", file);

    if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME)
    {
        if (TREE_LANG_FLAG_0 (node))
            fputs (" tree_0", file);
        if (TREE_LANG_FLAG_1 (node))
            fputs (" tree_1", file);
        if (TREE_LANG_FLAG_2 (node))
            fputs (" tree_2", file);
        if (TREE_LANG_FLAG_3 (node))
            fputs (" tree_3", file);
        if (TREE_LANG_FLAG_4 (node))
            fputs (" tree_4", file);
        if (TREE_LANG_FLAG_5 (node))
            fputs (" tree_5", file);
        if (TREE_LANG_FLAG_6 (node))
            fputs (" tree_6", file);
    }

    /* DECL_ nodes have additional attributes.  */

    switch (TREE_CODE_CLASS (code))
    {
    case tcc_declaration:
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            if (DECL_UNSIGNED (node))
                fputs (" unsigned", file);
            if (DECL_IGNORED_P (node))
                fputs (" ignored", file);
            if (DECL_ABSTRACT_P (node))
                fputs (" abstract", file);
            if (DECL_EXTERNAL (node))
                fputs (" external", file);
            if (DECL_NONLOCAL (node))
                fputs (" nonlocal", file);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS))
        {
            if (DECL_WEAK (node))
                fputs (" weak", file);
            if (DECL_IN_SYSTEM_HEADER (node))
                fputs (" in_system_header", file);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)
                && code != LABEL_DECL
                && code != FUNCTION_DECL
                && DECL_REGISTER (node))
            fputs (" regdecl", file);

        if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
            fputs (" suppress-debug", file);

        if (code == FUNCTION_DECL
                && DECL_FUNCTION_SPECIFIC_TARGET (node))
            fputs (" function-specific-target", file);
        if (code == FUNCTION_DECL
                && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node))
            fputs (" function-specific-opt", file);
        if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (node))
            fputs (" autoinline", file);
        if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
            fputs (" built-in", file);
        if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node))
            fputs (" static-chain", file);
        if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node))
            fputs (" tm-clone", file);

        if (code == FIELD_DECL && DECL_PACKED (node))
            fputs (" packed", file);
        if (code == FIELD_DECL && DECL_BIT_FIELD (node))
            fputs (" bit-field", file);
        if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (node))
            fputs (" nonaddressable", file);

        if (code == LABEL_DECL && EH_LANDING_PAD_NR (node))
            fprintf (file, " landing-pad:%d", EH_LANDING_PAD_NR (node));

        if (code == VAR_DECL && DECL_IN_TEXT_SECTION (node))
            fputs (" in-text-section", file);
        if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (node))
            fputs (" in-constant-pool", file);
        if (code == VAR_DECL && DECL_COMMON (node))
            fputs (" common", file);
        if (code == VAR_DECL && DECL_THREAD_LOCAL_P (node))
        {
            fputs (" ", file);
            fputs (tls_model_names[DECL_TLS_MODEL (node)], file);
        }

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            if (DECL_VIRTUAL_P (node))
                fputs (" virtual", file);
            if (DECL_PRESERVE_P (node))
                fputs (" preserve", file);
            if (DECL_LANG_FLAG_0 (node))
                fputs (" decl_0", file);
            if (DECL_LANG_FLAG_1 (node))
                fputs (" decl_1", file);
            if (DECL_LANG_FLAG_2 (node))
                fputs (" decl_2", file);
            if (DECL_LANG_FLAG_3 (node))
                fputs (" decl_3", file);
            if (DECL_LANG_FLAG_4 (node))
                fputs (" decl_4", file);
            if (DECL_LANG_FLAG_5 (node))
                fputs (" decl_5", file);
            if (DECL_LANG_FLAG_6 (node))
                fputs (" decl_6", file);
            if (DECL_LANG_FLAG_7 (node))
                fputs (" decl_7", file);

            mode = DECL_MODE (node);
            fprintf (file, " %s", GET_MODE_NAME (mode));
        }

        if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
                && DECL_BY_REFERENCE (node))
            fputs (" passed-by-reference", file);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)  && DECL_DEFER_OUTPUT (node))
            fputs (" defer-output", file);


        xloc = expand_location (DECL_SOURCE_LOCATION (node));
        fprintf (file, " file %s line %d col %d", xloc.file, xloc.line,
                 xloc.column);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            print_node (file, "size", DECL_SIZE (node), indent + 4);
            print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);

            if (code != FUNCTION_DECL || DECL_BUILT_IN (node))
                indent_to (file, indent + 3);

            if (DECL_USER_ALIGN (node))
                fprintf (file, " user");

            fprintf (file, " align %d", DECL_ALIGN (node));
            if (code == FIELD_DECL)
                fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED,
                         DECL_OFFSET_ALIGN (node));

            if (code == FUNCTION_DECL && DECL_BUILT_IN (node))
            {
                if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD)
                    fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node));
                else
                    fprintf (file, " built-in %s:%s",
                             built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)],
                             built_in_names[(int) DECL_FUNCTION_CODE (node)]);
            }
        }
        if (code == FIELD_DECL)
        {
            print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4);
            print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node),
                        indent + 4);
            if (DECL_BIT_FIELD_TYPE (node))
                print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node),
                            indent + 4);
        }

        print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4);

        if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON))
        {
            print_node_brief (file, "attributes",
                              DECL_ATTRIBUTES (node), indent + 4);
            if (code != PARM_DECL)
                print_node_brief (file, "initial", DECL_INITIAL (node),
                                  indent + 4);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL))
        {
            print_node_brief (file, "abstract_origin",
                              DECL_ABSTRACT_ORIGIN (node), indent + 4);
        }
        if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON))
        {
            print_node (file, "result", DECL_RESULT_FLD (node), indent + 4);
        }

        lang_hooks.print_decl (file, node, indent);

        if (DECL_RTL_SET_P (node))
        {
            indent_to (file, indent + 4);
            print_rtl (file, DECL_RTL (node));
        }

        if (code == PARM_DECL)
        {
            print_node (file, "arg-type", DECL_ARG_TYPE (node), indent + 4);

            if (DECL_INCOMING_RTL (node) != 0)
            {
                indent_to (file, indent + 4);
                fprintf (file, "incoming-rtl ");
                print_rtl (file, DECL_INCOMING_RTL (node));
            }
        }
        else if (code == FUNCTION_DECL
                 && DECL_STRUCT_FUNCTION (node) != 0)
        {
            print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4);
            indent_to (file, indent + 4);
            dump_addr (file, "struct-function ", DECL_STRUCT_FUNCTION (node));
        }

        if ((code == VAR_DECL || code == PARM_DECL)
                && DECL_HAS_VALUE_EXPR_P (node))
            print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4);

        /* Print the decl chain only if decl is at second level.  */
        if (indent == 4)
            print_node (file, "chain", TREE_CHAIN (node), indent + 4);
        else
            print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
        break;

    case tcc_type:
        if (TYPE_UNSIGNED (node))
            fputs (" unsigned", file);

        if (TYPE_NO_FORCE_BLK (node))
            fputs (" no-force-blk", file);

        if (TYPE_STRING_FLAG (node))
            fputs (" string-flag", file);

        if (TYPE_NEEDS_CONSTRUCTING (node))
            fputs (" needs-constructing", file);

        if ((code == RECORD_TYPE
                || code == UNION_TYPE
                || code == QUAL_UNION_TYPE
                || code == ARRAY_TYPE)
                && TYPE_REVERSE_STORAGE_ORDER (node))
            fputs (" reverse-storage-order", file);

        /* The transparent-union flag is used for different things in
        different nodes.  */
        if ((code == UNION_TYPE || code == RECORD_TYPE)
                && TYPE_TRANSPARENT_AGGR (node))
            fputs (" transparent-aggr", file);
        else if (code == ARRAY_TYPE
                 && TYPE_NONALIASED_COMPONENT (node))
            fputs (" nonaliased-component", file);

        if (TYPE_PACKED (node))
            fputs (" packed", file);

        if (TYPE_RESTRICT (node))
            fputs (" restrict", file);

        if (TYPE_LANG_FLAG_0 (node))
            fputs (" type_0", file);
        if (TYPE_LANG_FLAG_1 (node))
            fputs (" type_1", file);
        if (TYPE_LANG_FLAG_2 (node))
            fputs (" type_2", file);
        if (TYPE_LANG_FLAG_3 (node))
            fputs (" type_3", file);
        if (TYPE_LANG_FLAG_4 (node))
            fputs (" type_4", file);
        if (TYPE_LANG_FLAG_5 (node))
            fputs (" type_5", file);
        if (TYPE_LANG_FLAG_6 (node))
            fputs (" type_6", file);
        if (TYPE_LANG_FLAG_7 (node))
            fputs (" type_7", file);

        mode = TYPE_MODE (node);
        fprintf (file, " %s", GET_MODE_NAME (mode));

        print_node (file, "size", TYPE_SIZE (node), indent + 4);
        print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4);
        indent_to (file, indent + 3);

        if (TYPE_USER_ALIGN (node))
            fprintf (file, " user");

        fprintf (file, " align %d symtab %d alias set " HOST_WIDE_INT_PRINT_DEC,
                 TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node),
                 (HOST_WIDE_INT) TYPE_ALIAS_SET (node));

        if (TYPE_STRUCTURAL_EQUALITY_P (node))
            fprintf (file, " structural equality");
        else
            dump_addr (file, " canonical type ", TYPE_CANONICAL (node));

        print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4);

        if (INTEGRAL_TYPE_P (node) || code == REAL_TYPE
                || code == FIXED_POINT_TYPE)
        {
            fprintf (file, " precision %d", TYPE_PRECISION (node));
            print_node_brief (file, "min", TYPE_MIN_VALUE (node), indent + 4);
            print_node_brief (file, "max", TYPE_MAX_VALUE (node), indent + 4);
        }

        if (code == ENUMERAL_TYPE)
            print_node (file, "values", TYPE_VALUES (node), indent + 4);
        else if (code == ARRAY_TYPE)
            print_node (file, "domain", TYPE_DOMAIN (node), indent + 4);
        else if (code == VECTOR_TYPE)
            fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node));
        else if (code == RECORD_TYPE
                 || code == UNION_TYPE
                 || code == QUAL_UNION_TYPE)
            print_node (file, "fields", TYPE_FIELDS (node), indent + 4);
        else if (code == FUNCTION_TYPE
                 || code == METHOD_TYPE)
        {
            if (TYPE_METHOD_BASETYPE (node))
                print_node_brief (file, "method basetype",
                                  TYPE_METHOD_BASETYPE (node), indent + 4);
            print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4);
        }
        else if (code == OFFSET_TYPE)
            print_node_brief (file, "basetype", TYPE_OFFSET_BASETYPE (node),
                              indent + 4);

        if (TYPE_CONTEXT (node))
            print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4);

        lang_hooks.print_type (file, node, indent);

        if (TYPE_POINTER_TO (node) || TREE_CHAIN (node))
            indent_to (file, indent + 3);

        print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node),
                          indent + 4);
        print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node),
                          indent + 4);
        print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4);
        break;

    case tcc_expression:
    case tcc_comparison:
    case tcc_unary:
    case tcc_binary:
    case tcc_reference:
    case tcc_statement:
    case tcc_vl_exp:
        if (code == BIND_EXPR)
        {
            print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4);
            print_node (file, "body", TREE_OPERAND (node, 1), indent + 4);
            print_node (file, "block", TREE_OPERAND (node, 2), indent + 4);
            break;
        }
        if (code == CALL_EXPR)
        {
            call_expr_arg_iterator iter;
            tree arg;
            print_node (file, "fn", CALL_EXPR_FN (node), indent + 4);
            print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node),
                        indent + 4);
            i = 0;
            FOR_EACH_CALL_EXPR_ARG (arg, iter, node)
            {
                char temp[10];
                sprintf (temp, "arg %d", i);
                print_node (file, temp, arg, indent + 4);
                i++;
            }
        }
コード例 #15
0
static void
dequeue_and_dump (dump_info_p di)
{
  dump_queue_p dq;
  splay_tree_node stn;
  dump_node_info_p dni;
  tree t;
  unsigned int index;
  enum tree_code code;
  enum tree_code_class code_class;
  const char* code_name;

  /* Get the next node from the queue.  */
  dq = di->queue;
  stn = dq->node;
  t = (tree) stn->key;
  dni = (dump_node_info_p) stn->value;
  index = dni->index;

  /* Remove the node from the queue, and put it on the free list.  */
  di->queue = dq->next;
  if (!di->queue)
    di->queue_end = 0;
  dq->next = di->free_list;
  di->free_list = dq;

  /* Print the node index.  */
  dump_index (di, index);
  /* And the type of node this is.  */
  if (dni->binfo_p)
    code_name = "binfo";
  else
    code_name = tree_code_name[(int) TREE_CODE (t)];
  fprintf (di->stream, "%-16s ", code_name);
  di->column = 25;

  /* Figure out what kind of node this is.  */
  code = TREE_CODE (t);
  code_class = TREE_CODE_CLASS (code);

  /* Although BINFOs are TREE_VECs, we dump them specially so as to be
     more informative.  */
  if (dni->binfo_p)
    {
      unsigned ix;
      tree base;
      VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (t);

      dump_child ("type", BINFO_TYPE (t));

      if (BINFO_VIRTUAL_P (t))
	dump_string_field (di, "spec", "virt");

      dump_int (di, "bases", BINFO_N_BASE_BINFOS (t));
      for (ix = 0; BINFO_BASE_ITERATE (t, ix, base); ix++)
	{
	  tree access = (accesses ? VEC_index (tree, accesses, ix)
			 : access_public_node);
	  const char *string = NULL;

	  if (access == access_public_node)
	    string = "pub";
	  else if (access == access_protected_node)
	    string = "prot";
	  else if (access == access_private_node)
	    string = "priv";
	  else
	    gcc_unreachable ();

	  dump_string_field (di, "accs", string);
	  queue_and_dump_index (di, "binf", base, DUMP_BINFO);
	}

      goto done;
    }

  /* We can knock off a bunch of expression nodes in exactly the same
     way.  */
  if (IS_EXPR_CODE_CLASS (code_class))
    {
      /* If we're dumping children, dump them now.  */
      queue_and_dump_type (di, t);

      switch (code_class)
	{
	case tcc_unary:
	  dump_child ("op 0", TREE_OPERAND (t, 0));
	  break;

	case tcc_binary:
	case tcc_comparison:
	  dump_child ("op 0", TREE_OPERAND (t, 0));
	  dump_child ("op 1", TREE_OPERAND (t, 1));
	  break;

	case tcc_expression:
	case tcc_reference:
	case tcc_statement:
	case tcc_vl_exp:
	  /* These nodes are handled explicitly below.  */
	  break;

	default:
	  gcc_unreachable ();
	}
    }
  else if (DECL_P (t))
    {
      expanded_location xloc;
      /* All declarations have names.  */
      if (DECL_NAME (t))
	dump_child ("name", DECL_NAME (t));
      if (DECL_ASSEMBLER_NAME_SET_P (t)
	  && DECL_ASSEMBLER_NAME (t) != DECL_NAME (t))
	dump_child ("mngl", DECL_ASSEMBLER_NAME (t));
      if (DECL_ABSTRACT_ORIGIN (t))
        dump_child ("orig", DECL_ABSTRACT_ORIGIN (t));
      /* And types.  */
      queue_and_dump_type (di, t);
      dump_child ("scpe", DECL_CONTEXT (t));
      /* And a source position.  */
      xloc = expand_location (DECL_SOURCE_LOCATION (t));
      if (xloc.file)
	{
	  const char *filename = lbasename (xloc.file);

	  dump_maybe_newline (di);
	  fprintf (di->stream, "srcp: %s:%-6d ", filename,
		   xloc.line);
	  di->column += 6 + strlen (filename) + 8;
	}
      /* And any declaration can be compiler-generated.  */
      if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_COMMON)
	  && DECL_ARTIFICIAL (t))
	dump_string_field (di, "note", "artificial");
      if (DECL_CHAIN (t) && !dump_flag (di, TDF_SLIM, NULL))
	dump_child ("chain", DECL_CHAIN (t));
    }
  else if (code_class == tcc_type)
    {
      /* All types have qualifiers.  */
      int quals = lang_hooks.tree_dump.type_quals (t);

      if (quals != TYPE_UNQUALIFIED)
	{
	  fprintf (di->stream, "qual: %c%c%c     ",
		   (quals & TYPE_QUAL_CONST) ? 'c' : ' ',
		   (quals & TYPE_QUAL_VOLATILE) ? 'v' : ' ',
		   (quals & TYPE_QUAL_RESTRICT) ? 'r' : ' ');
	  di->column += 14;
	}

      /* All types have associated declarations.  */
      dump_child ("name", TYPE_NAME (t));

      /* All types have a main variant.  */
      if (TYPE_MAIN_VARIANT (t) != t)
	dump_child ("unql", TYPE_MAIN_VARIANT (t));

      /* And sizes.  */
      dump_child ("size", TYPE_SIZE (t));

      /* All types have alignments.  */
      dump_int (di, "algn", TYPE_ALIGN (t));
    }
  else if (code_class == tcc_constant)
    /* All constants can have types.  */
    queue_and_dump_type (di, t);

  /* Give the language-specific code a chance to print something.  If
     it's completely taken care of things, don't bother printing
     anything more ourselves.  */
  if (lang_hooks.tree_dump.dump_tree (di, t))
    goto done;

  /* Now handle the various kinds of nodes.  */
  switch (code)
    {
      int i;

    case IDENTIFIER_NODE:
      dump_string_field (di, "strg", IDENTIFIER_POINTER (t));
      dump_int (di, "lngt", IDENTIFIER_LENGTH (t));
      break;

    case TREE_LIST:
      dump_child ("purp", TREE_PURPOSE (t));
      dump_child ("valu", TREE_VALUE (t));
      dump_child ("chan", TREE_CHAIN (t));
      break;

    case STATEMENT_LIST:
      {
	tree_stmt_iterator it;
	for (i = 0, it = tsi_start (t); !tsi_end_p (it); tsi_next (&it), i++)
	  {
	    char buffer[32];
	    sprintf (buffer, "%u", i);
	    dump_child (buffer, tsi_stmt (it));
	  }
      }
      break;

    case TREE_VEC:
      dump_int (di, "lngt", TREE_VEC_LENGTH (t));
      for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
	{
	  char buffer[32];
	  sprintf (buffer, "%u", i);
	  dump_child (buffer, TREE_VEC_ELT (t, i));
	}
      break;

    case INTEGER_TYPE:
    case ENUMERAL_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
      dump_child ("min", TYPE_MIN_VALUE (t));
      dump_child ("max", TYPE_MAX_VALUE (t));

      if (code == ENUMERAL_TYPE)
	dump_child ("csts", TYPE_VALUES (t));
      break;

    case REAL_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      break;

    case FIXED_POINT_TYPE:
      dump_int (di, "prec", TYPE_PRECISION (t));
      dump_string_field (di, "sign", TYPE_UNSIGNED (t) ? "unsigned": "signed");
      dump_string_field (di, "saturating",
			 TYPE_SATURATING (t) ? "saturating": "non-saturating");
      break;

    case POINTER_TYPE:
      dump_child ("ptd", TREE_TYPE (t));
      break;

    case REFERENCE_TYPE:
      dump_child ("refd", TREE_TYPE (t));
      break;

    case METHOD_TYPE:
      dump_child ("clas", TYPE_METHOD_BASETYPE (t));
      /* Fall through.  */

    case FUNCTION_TYPE:
      dump_child ("retn", TREE_TYPE (t));
      dump_child ("prms", TYPE_ARG_TYPES (t));
      break;

    case ARRAY_TYPE:
      dump_child ("elts", TREE_TYPE (t));
      dump_child ("domn", TYPE_DOMAIN (t));
      break;

    case RECORD_TYPE:
    case UNION_TYPE:
      if (TREE_CODE (t) == RECORD_TYPE)
	dump_string_field (di, "tag", "struct");
      else
	dump_string_field (di, "tag", "union");

      dump_child ("flds", TYPE_FIELDS (t));
      dump_child ("fncs", TYPE_METHODS (t));
      queue_and_dump_index (di, "binf", TYPE_BINFO (t),
			    DUMP_BINFO);
      break;

    case CONST_DECL:
      dump_child ("cnst", DECL_INITIAL (t));
      break;

    case DEBUG_EXPR_DECL:
      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
      /* Fall through.  */

    case VAR_DECL:
    case PARM_DECL:
    case FIELD_DECL:
    case RESULT_DECL:
      if (TREE_CODE (t) == PARM_DECL)
	dump_child ("argt", DECL_ARG_TYPE (t));
      else
	dump_child ("init", DECL_INITIAL (t));
      dump_child ("size", DECL_SIZE (t));
      dump_int (di, "algn", DECL_ALIGN (t));

      if (TREE_CODE (t) == FIELD_DECL)
	{
	  if (DECL_FIELD_OFFSET (t))
	    dump_child ("bpos", bit_position (t));
	}
      else if (TREE_CODE (t) == VAR_DECL
	       || TREE_CODE (t) == PARM_DECL)
	{
	  dump_int (di, "used", TREE_USED (t));
	  if (DECL_REGISTER (t))
	    dump_string_field (di, "spec", "register");
	}
      break;

    case FUNCTION_DECL:
      dump_child ("args", DECL_ARGUMENTS (t));
      if (DECL_EXTERNAL (t))
	dump_string_field (di, "body", "undefined");
      if (TREE_PUBLIC (t))
	dump_string_field (di, "link", "extern");
      else
	dump_string_field (di, "link", "static");
      if (DECL_SAVED_TREE (t) && !dump_flag (di, TDF_SLIM, t))
	dump_child ("body", DECL_SAVED_TREE (t));
      break;

    case INTEGER_CST:
      if (TREE_INT_CST_HIGH (t))
	dump_int (di, "high", TREE_INT_CST_HIGH (t));
      dump_int (di, "low", TREE_INT_CST_LOW (t));
      break;

    case STRING_CST:
      fprintf (di->stream, "strg: %-7s ", TREE_STRING_POINTER (t));
      dump_int (di, "lngt", TREE_STRING_LENGTH (t));
      break;

    case REAL_CST:
      dump_real (di, "valu", TREE_REAL_CST_PTR (t));
      break;

    case FIXED_CST:
      dump_fixed (di, "valu", TREE_FIXED_CST_PTR (t));
      break;

    case TRUTH_NOT_EXPR:
    case ADDR_EXPR:
    case INDIRECT_REF:
    case CLEANUP_POINT_EXPR:
    case SAVE_EXPR:
    case REALPART_EXPR:
    case IMAGPART_EXPR:
      /* These nodes are unary, but do not have code class `1'.  */
      dump_child ("op 0", TREE_OPERAND (t, 0));
      break;

    case TRUTH_ANDIF_EXPR:
    case TRUTH_ORIF_EXPR:
    case INIT_EXPR:
    case MODIFY_EXPR:
    case COMPOUND_EXPR:
    case PREDECREMENT_EXPR:
    case PREINCREMENT_EXPR:
    case POSTDECREMENT_EXPR:
    case POSTINCREMENT_EXPR:
      /* These nodes are binary, but do not have code class `2'.  */
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      break;

    case COMPONENT_REF:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      break;

    case ARRAY_REF:
    case ARRAY_RANGE_REF:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      dump_child ("op 3", TREE_OPERAND (t, 3));
      break;

    case COND_EXPR:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      dump_child ("op 2", TREE_OPERAND (t, 2));
      break;

    case TRY_FINALLY_EXPR:
      dump_child ("op 0", TREE_OPERAND (t, 0));
      dump_child ("op 1", TREE_OPERAND (t, 1));
      break;

    case CALL_EXPR:
      {
	int i = 0;
	tree arg;
	call_expr_arg_iterator iter;
	dump_child ("fn", CALL_EXPR_FN (t));
	FOR_EACH_CALL_EXPR_ARG (arg, iter, t)
	  {
	    char buffer[32];
	    sprintf (buffer, "%u", i);
	    dump_child (buffer, arg);
	    i++;
	  }
      }
      break;

    case CONSTRUCTOR:
      {
	unsigned HOST_WIDE_INT cnt;
	tree index, value;
	dump_int (di, "lngt", VEC_length (constructor_elt,
					  CONSTRUCTOR_ELTS (t)));
	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), cnt, index, value)
	  {
	    dump_child ("idx", index);
	    dump_child ("val", value);
	  }
      }
コード例 #16
0
ファイル: ubsan.c プロジェクト: acoxepochlabs/gcc
static void
instrument_bool_enum_load (gimple_stmt_iterator *gsi)
{
  gimple stmt = gsi_stmt (*gsi);
  tree rhs = gimple_assign_rhs1 (stmt);
  tree type = TREE_TYPE (rhs);
  tree minv = NULL_TREE, maxv = NULL_TREE;

  if (TREE_CODE (type) == BOOLEAN_TYPE && (flag_sanitize & SANITIZE_BOOL))
    {
      minv = boolean_false_node;
      maxv = boolean_true_node;
    }
  else if (TREE_CODE (type) == ENUMERAL_TYPE
	   && (flag_sanitize & SANITIZE_ENUM)
	   && TREE_TYPE (type) != NULL_TREE
	   && TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE
	   && (TYPE_PRECISION (TREE_TYPE (type))
	       < GET_MODE_PRECISION (TYPE_MODE (type))))
    {
      minv = TYPE_MIN_VALUE (TREE_TYPE (type));
      maxv = TYPE_MAX_VALUE (TREE_TYPE (type));
    }
  else
    return;

  int modebitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
  HOST_WIDE_INT bitsize, bitpos;
  tree offset;
  enum machine_mode mode;
  int volatilep = 0, unsignedp = 0;
  tree base = get_inner_reference (rhs, &bitsize, &bitpos, &offset, &mode,
				   &unsignedp, &volatilep, false);
  tree utype = build_nonstandard_integer_type (modebitsize, 1);

  if ((TREE_CODE (base) == VAR_DECL && DECL_HARD_REGISTER (base))
      || (bitpos % modebitsize) != 0
      || bitsize != modebitsize
      || GET_MODE_BITSIZE (TYPE_MODE (utype)) != modebitsize
      || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
    return;

  location_t loc = gimple_location (stmt);
  tree ptype = build_pointer_type (TREE_TYPE (rhs));
  tree atype = reference_alias_ptr_type (rhs);
  gimple g = gimple_build_assign (make_ssa_name (ptype, NULL),
				  build_fold_addr_expr (rhs));
  gimple_set_location (g, loc);
  gsi_insert_before (gsi, g, GSI_SAME_STMT);
  tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g),
		     build_int_cst (atype, 0));
  tree urhs = make_ssa_name (utype, NULL);
  g = gimple_build_assign (urhs, mem);
  gimple_set_location (g, loc);
  gsi_insert_before (gsi, g, GSI_SAME_STMT);
  minv = fold_convert (utype, minv);
  maxv = fold_convert (utype, maxv);
  if (!integer_zerop (minv))
    {
      g = gimple_build_assign_with_ops (MINUS_EXPR,
					make_ssa_name (utype, NULL),
					urhs, minv);
      gimple_set_location (g, loc);
      gsi_insert_before (gsi, g, GSI_SAME_STMT);
    }

  gimple_stmt_iterator gsi2 = *gsi;
  basic_block then_bb, fallthru_bb;
  *gsi = create_cond_insert_point (gsi, true, false, true,
				   &then_bb, &fallthru_bb);
  g = gimple_build_cond (GT_EXPR, gimple_assign_lhs (g),
			 int_const_binop (MINUS_EXPR, maxv, minv),
			 NULL_TREE, NULL_TREE);
  gimple_set_location (g, loc);
  gsi_insert_after (gsi, g, GSI_NEW_STMT);

  gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE);
  update_stmt (stmt);

  gsi2 = gsi_after_labels (then_bb);
  if (flag_sanitize_undefined_trap_on_error)
    g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
  else
    {
      tree data = ubsan_create_data ("__ubsan_invalid_value_data", &loc, NULL,
				     ubsan_type_descriptor (type), NULL_TREE);
      data = build_fold_addr_expr_loc (loc, data);
      enum built_in_function bcode
	= flag_sanitize_recover
	  ? BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE
	  : BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT;
      tree fn = builtin_decl_explicit (bcode);

      tree val = force_gimple_operand_gsi (&gsi2, ubsan_encode_value (urhs),
					   true, NULL_TREE, true,
					   GSI_SAME_STMT);
      g = gimple_build_call (fn, 2, data, val);
    }
  gimple_set_location (g, loc);
  gsi_insert_before (&gsi2, g, GSI_SAME_STMT);
}
コード例 #17
0
ファイル: lighthouse-tree.c プロジェクト: ctz/lighthouse
void xml_type(tree t, tree opt_decl, int indent, FILE *out)
{
    tree a = NULL;

    if (AGGREGATE_TYPE_P(t))
        return xml_type_ref(t, indent, out);

    switch (TREE_CODE(t))
    {
    case POINTER_TYPE:
        fprintf(out, "%s<addr-of", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, ">\n");
        xml_type(TREE_TYPE(t), NULL, indent + INDENT, out);
        fprintf(out, "%s</addr-of>\n", spc(indent));
        break;

    case REAL_TYPE:
        fprintf(out, "%s<float", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, " precision='%d'", TYPE_PRECISION(t));
        fprintf(out, " />\n");
        break;

    case INTEGER_TYPE:
        fprintf(out, "%s<integer", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        if (TYPE_UNSIGNED(t))
            fprintf(out, " unsigned='1'");
        fprintf(out, " precision='%d'", TYPE_PRECISION(t));

        /* TREE_TYPE here indicates that there is an interesting domain. */
        if (TREE_TYPE(t) && TYPE_MIN_VALUE(t))
            fprintf(out, (TYPE_UNSIGNED(t) ? " min='%llu'" : " min='%lld'"), double_int_to_ll(TREE_INT_CST(TYPE_MIN_VALUE(t))));
        if (TREE_TYPE(t) && TYPE_MAX_VALUE(t))
            fprintf(out, (TYPE_UNSIGNED(t) ? " max='%llu'" : " max='%lld'"), double_int_to_ll(TREE_INT_CST(TYPE_MAX_VALUE(t))));
        fprintf(out, " />\n");
        break;

    case VOID_TYPE:
        fprintf(out, "%s<void />\n", spc(indent));
        break;

    case BOOLEAN_TYPE:
        fprintf(out, "%s<boolean />\n", spc(indent));
        break;

    case RESULT_DECL:
        fprintf(out, "%s<result />\n", spc(indent));
        break;

    case ENUMERAL_TYPE:
        /* TODO: finish this (output tags). */
        fprintf(out, "%s<enum", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        fprintf(out, " />\n");
        break;

    case METHOD_TYPE:
    case FUNCTION_TYPE:
        fprintf(out, "%s<function", spc(indent));
        xml_type_quals(TYPE_QUALS(t), out);
        xml_type_name(TYPE_NAME(t), out);
        xml_type_attribs(TYPE_ATTRIBUTES(t),
                         (opt_decl && TREE_THIS_VOLATILE(opt_decl)) ? "noreturn" : NULL,
                         out);
        indent += INDENT;
        fprintf(out, ">\n%s<return>\n", spc(indent));
        xml_type(TREE_TYPE(t), NULL, indent + INDENT, out);
        fprintf(out, "%s</return>\n", spc(indent));

        /* varargs if last is not void. */
        for (a = TYPE_ARG_TYPES(t); a && TREE_CHAIN(a); a = TREE_CHAIN(a))
            ;

        fprintf(out, "%s<arguments %s>\n", spc(indent),
                (!a || TREE_CODE(TREE_VALUE(a)) == VOID_TYPE) ? "" : "varargs='1' ");

        for (a = TYPE_ARG_TYPES(t); a; a = TREE_CHAIN(a))
        {
            xml_type(TREE_VALUE(a), NULL, indent + INDENT, out);
        }

        fprintf(out, "%s</arguments>\n", spc(indent));
        indent -= INDENT;
        fprintf(out, "%s</function>\n", spc(indent));
        break;

    case REFERENCE_TYPE:
        fprintf(stderr, "lighthouse warning: ignoring unhandled tree type '%s'.\n",
                tree_code_name[TREE_CODE(t)]);
        break;

    default:
        fprintf(stderr, "failing: unhandled tree type %s\n",
                tree_code_name[TREE_CODE(t)]);
        assert(0);
        abort();
    }
}
コード例 #18
0
ファイル: c-omp.c プロジェクト: ymgcmstk/gcc
tree
c_finish_omp_for (location_t locus, enum tree_code code, tree declv,
		  tree orig_declv, tree initv, tree condv, tree incrv,
		  tree body, tree pre_body)
{
  location_t elocus;
  bool fail = false;
  int i;

  if ((code == CILK_SIMD || code == CILK_FOR)
      && !c_check_cilk_loop (locus, TREE_VEC_ELT (declv, 0)))
    fail = true;

  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv));
  gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv));
  for (i = 0; i < TREE_VEC_LENGTH (declv); i++)
    {
      tree decl = TREE_VEC_ELT (declv, i);
      tree init = TREE_VEC_ELT (initv, i);
      tree cond = TREE_VEC_ELT (condv, i);
      tree incr = TREE_VEC_ELT (incrv, i);

      elocus = locus;
      if (EXPR_HAS_LOCATION (init))
	elocus = EXPR_LOCATION (init);

      /* Validate the iteration variable.  */
      if (!INTEGRAL_TYPE_P (TREE_TYPE (decl))
	  && TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE)
	{
	  error_at (elocus, "invalid type for iteration variable %qE", decl);
	  fail = true;
	}

      /* In the case of "for (int i = 0...)", init will be a decl.  It should
	 have a DECL_INITIAL that we can turn into an assignment.  */
      if (init == decl)
	{
	  elocus = DECL_SOURCE_LOCATION (decl);

	  init = DECL_INITIAL (decl);
	  if (init == NULL)
	    {
	      error_at (elocus, "%qE is not initialized", decl);
	      init = integer_zero_node;
	      fail = true;
	    }
	  DECL_INITIAL (decl) = NULL_TREE;

	  init = build_modify_expr (elocus, decl, NULL_TREE, NOP_EXPR,
	      			    /* FIXME diagnostics: This should
				       be the location of the INIT.  */
	      			    elocus,
				    init,
				    NULL_TREE);
	}
      if (init != error_mark_node)
	{
	  gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
	  gcc_assert (TREE_OPERAND (init, 0) == decl);
	}

      if (cond == NULL_TREE)
	{
	  error_at (elocus, "missing controlling predicate");
	  fail = true;
	}
      else
	{
	  bool cond_ok = false;

	  if (EXPR_HAS_LOCATION (cond))
	    elocus = EXPR_LOCATION (cond);

	  if (TREE_CODE (cond) == LT_EXPR
	      || TREE_CODE (cond) == LE_EXPR
	      || TREE_CODE (cond) == GT_EXPR
	      || TREE_CODE (cond) == GE_EXPR
	      || TREE_CODE (cond) == NE_EXPR
	      || TREE_CODE (cond) == EQ_EXPR)
	    {
	      tree op0 = TREE_OPERAND (cond, 0);
	      tree op1 = TREE_OPERAND (cond, 1);

	      /* 2.5.1.  The comparison in the condition is computed in
		 the type of DECL, otherwise the behavior is undefined.

		 For example:
		 long n; int i;
		 i < n;

		 according to ISO will be evaluated as:
		 (long)i < n;

		 We want to force:
		 i < (int)n;  */
	      if (TREE_CODE (op0) == NOP_EXPR
		  && decl == TREE_OPERAND (op0, 0))
		{
		  TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
		  TREE_OPERAND (cond, 1)
		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
				   TREE_OPERAND (cond, 1));
		}
	      else if (TREE_CODE (op1) == NOP_EXPR
		       && decl == TREE_OPERAND (op1, 0))
		{
		  TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
		  TREE_OPERAND (cond, 0)
		    = fold_build1_loc (elocus, NOP_EXPR, TREE_TYPE (decl),
				   TREE_OPERAND (cond, 0));
		}

	      if (decl == TREE_OPERAND (cond, 0))
		cond_ok = true;
	      else if (decl == TREE_OPERAND (cond, 1))
		{
		  TREE_SET_CODE (cond,
				 swap_tree_comparison (TREE_CODE (cond)));
		  TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
		  TREE_OPERAND (cond, 0) = decl;
		  cond_ok = true;
		}

	      if (TREE_CODE (cond) == NE_EXPR
		  || TREE_CODE (cond) == EQ_EXPR)
		{
		  if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
		    {
		      if (code != CILK_SIMD && code != CILK_FOR)
			cond_ok = false;
		    }
		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
					    TYPE_MIN_VALUE (TREE_TYPE (decl)),
					    0))
		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
					 ? GT_EXPR : LE_EXPR);
		  else if (operand_equal_p (TREE_OPERAND (cond, 1),
					    TYPE_MAX_VALUE (TREE_TYPE (decl)),
					    0))
		    TREE_SET_CODE (cond, TREE_CODE (cond) == NE_EXPR
					 ? LT_EXPR : GE_EXPR);
		  else if (code != CILK_SIMD && code != CILK_FOR)
		    cond_ok = false;
		}
	    }

	  if (!cond_ok)
	    {
	      error_at (elocus, "invalid controlling predicate");
	      fail = true;
	    }
	}

      if (incr == NULL_TREE)
	{
	  error_at (elocus, "missing increment expression");
	  fail = true;
	}
      else
	{
	  bool incr_ok = false;

	  if (EXPR_HAS_LOCATION (incr))
	    elocus = EXPR_LOCATION (incr);

	  /* Check all the valid increment expressions: v++, v--, ++v, --v,
	     v = v + incr, v = incr + v and v = v - incr.  */
	  switch (TREE_CODE (incr))
	    {
	    case POSTINCREMENT_EXPR:
	    case PREINCREMENT_EXPR:
	    case POSTDECREMENT_EXPR:
	    case PREDECREMENT_EXPR:
	      if (TREE_OPERAND (incr, 0) != decl)
		break;

	      incr_ok = true;
	      incr = c_omp_for_incr_canonicalize_ptr (elocus, decl, incr);
	      break;

	    case COMPOUND_EXPR:
	      if (TREE_CODE (TREE_OPERAND (incr, 0)) != SAVE_EXPR
		  || TREE_CODE (TREE_OPERAND (incr, 1)) != MODIFY_EXPR)
		break;
	      incr = TREE_OPERAND (incr, 1);
	      /* FALLTHRU */
	    case MODIFY_EXPR:
	      if (TREE_OPERAND (incr, 0) != decl)
		break;
	      if (TREE_OPERAND (incr, 1) == decl)
		break;
	      if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
		  && (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
		      || TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
		incr_ok = true;
	      else if ((TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
			|| (TREE_CODE (TREE_OPERAND (incr, 1))
			    == POINTER_PLUS_EXPR))
		       && TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
		incr_ok = true;
	      else
		{
		  tree t = check_omp_for_incr_expr (elocus,
						    TREE_OPERAND (incr, 1),
						    decl);
		  if (t != error_mark_node)
		    {
		      incr_ok = true;
		      t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
		      incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
		    }
		}
	      break;

	    default:
	      break;
	    }
	  if (!incr_ok)
	    {
	      error_at (elocus, "invalid increment expression");
	      fail = true;
	    }
	}

      TREE_VEC_ELT (initv, i) = init;
      TREE_VEC_ELT (incrv, i) = incr;
    }

  if (fail)
    return NULL;
  else
    {
      tree t = make_node (code);

      TREE_TYPE (t) = void_type_node;
      OMP_FOR_INIT (t) = initv;
      OMP_FOR_COND (t) = condv;
      OMP_FOR_INCR (t) = incrv;
      OMP_FOR_BODY (t) = body;
      OMP_FOR_PRE_BODY (t) = pre_body;
      if (code == OMP_FOR)
	OMP_FOR_ORIG_DECLS (t) = orig_declv;

      SET_EXPR_LOCATION (t, locus);
      return add_stmt (t);
    }
}
コード例 #19
0
ファイル: internal-fn.c プロジェクト: Alexpux/GCC
void
ubsan_expand_si_overflow_neg_check (gimple stmt)
{
  rtx res, op1;
  tree lhs, fn, arg1;
  rtx_code_label *done_label, *do_error;
  rtx target = NULL_RTX;

  lhs = gimple_call_lhs (stmt);
  arg1 = gimple_call_arg (stmt, 1);
  done_label = gen_label_rtx ();
  do_error = gen_label_rtx ();

  do_pending_stack_adjust ();
  op1 = expand_normal (arg1);

  machine_mode mode = TYPE_MODE (TREE_TYPE (arg1));
  if (lhs)
    target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);

  enum insn_code icode = optab_handler (negv3_optab, mode);
  if (icode != CODE_FOR_nothing)
    {
      struct expand_operand ops[3];
      rtx_insn *last = get_last_insn ();

      res = gen_reg_rtx (mode);
      create_output_operand (&ops[0], res, mode);
      create_input_operand (&ops[1], op1, mode);
      create_fixed_operand (&ops[2], do_error);
      if (maybe_expand_insn (icode, 3, ops))
	{
	  last = get_last_insn ();
	  if (profile_status_for_fn (cfun) != PROFILE_ABSENT
	      && JUMP_P (last)
	      && any_condjump_p (last)
	      && !find_reg_note (last, REG_BR_PROB, 0))
	    add_int_reg_note (last, REG_BR_PROB, PROB_VERY_UNLIKELY);
	  emit_jump (done_label);
        }
      else
	{
	  delete_insns_since (last);
	  icode = CODE_FOR_nothing;
	}
    }

  if (icode == CODE_FOR_nothing)
    {
      /* Compute the operation.  On RTL level, the addition is always
	 unsigned.  */
      res = expand_unop (mode, neg_optab, op1, NULL_RTX, false);

      /* Compare the operand with the most negative value.  */
      rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
      emit_cmp_and_jump_insns (op1, minv, NE, NULL_RTX, mode, false,
			       done_label, PROB_VERY_LIKELY);
    }

  emit_label (do_error);
  /* Expand the ubsan builtin call.  */
  push_temp_slots ();
  fn = ubsan_build_overflow_builtin (NEGATE_EXPR, gimple_location (stmt),
				     TREE_TYPE (arg1), arg1, NULL_TREE);
  expand_normal (fn);
  pop_temp_slots ();
  do_pending_stack_adjust ();

  /* We're done.  */
  emit_label (done_label);

  if (lhs)
    emit_move_insn (target, res);
}
コード例 #20
0
ファイル: omp-general.c プロジェクト: WojciechMigda/gcc
void
omp_extract_for_data (gomp_for *for_stmt, struct omp_for_data *fd,
		      struct omp_for_data_loop *loops)
{
  tree t, var, *collapse_iter, *collapse_count;
  tree count = NULL_TREE, iter_type = long_integer_type_node;
  struct omp_for_data_loop *loop;
  int i;
  struct omp_for_data_loop dummy_loop;
  location_t loc = gimple_location (for_stmt);
  bool simd = gimple_omp_for_kind (for_stmt) & GF_OMP_FOR_SIMD;
  bool distribute = gimple_omp_for_kind (for_stmt)
		    == GF_OMP_FOR_KIND_DISTRIBUTE;
  bool taskloop = gimple_omp_for_kind (for_stmt)
		  == GF_OMP_FOR_KIND_TASKLOOP;
  tree iterv, countv;

  fd->for_stmt = for_stmt;
  fd->pre = NULL;
  if (gimple_omp_for_collapse (for_stmt) > 1)
    fd->loops = loops;
  else
    fd->loops = &fd->loop;

  fd->have_nowait = distribute || simd;
  fd->have_ordered = false;
  fd->collapse = 1;
  fd->ordered = 0;
  fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
  fd->sched_modifiers = 0;
  fd->chunk_size = NULL_TREE;
  fd->simd_schedule = false;
  if (gimple_omp_for_kind (fd->for_stmt) == GF_OMP_FOR_KIND_CILKFOR)
    fd->sched_kind = OMP_CLAUSE_SCHEDULE_CILKFOR;
  collapse_iter = NULL;
  collapse_count = NULL;

  for (t = gimple_omp_for_clauses (for_stmt); t ; t = OMP_CLAUSE_CHAIN (t))
    switch (OMP_CLAUSE_CODE (t))
      {
      case OMP_CLAUSE_NOWAIT:
	fd->have_nowait = true;
	break;
      case OMP_CLAUSE_ORDERED:
	fd->have_ordered = true;
	if (OMP_CLAUSE_ORDERED_EXPR (t))
	  fd->ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (t));
	break;
      case OMP_CLAUSE_SCHEDULE:
	gcc_assert (!distribute && !taskloop);
	fd->sched_kind
	  = (enum omp_clause_schedule_kind)
	    (OMP_CLAUSE_SCHEDULE_KIND (t) & OMP_CLAUSE_SCHEDULE_MASK);
	fd->sched_modifiers = (OMP_CLAUSE_SCHEDULE_KIND (t)
			       & ~OMP_CLAUSE_SCHEDULE_MASK);
	fd->chunk_size = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (t);
	fd->simd_schedule = OMP_CLAUSE_SCHEDULE_SIMD (t);
	break;
      case OMP_CLAUSE_DIST_SCHEDULE:
	gcc_assert (distribute);
	fd->chunk_size = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (t);
	break;
      case OMP_CLAUSE_COLLAPSE:
	fd->collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (t));
	if (fd->collapse > 1)
	  {
	    collapse_iter = &OMP_CLAUSE_COLLAPSE_ITERVAR (t);
	    collapse_count = &OMP_CLAUSE_COLLAPSE_COUNT (t);
	  }
	break;
      default:
	break;
      }
  if (fd->ordered && fd->collapse == 1 && loops != NULL)
    {
      fd->loops = loops;
      iterv = NULL_TREE;
      countv = NULL_TREE;
      collapse_iter = &iterv;
      collapse_count = &countv;
    }

  /* FIXME: for now map schedule(auto) to schedule(static).
     There should be analysis to determine whether all iterations
     are approximately the same amount of work (then schedule(static)
     is best) or if it varies (then schedule(dynamic,N) is better).  */
  if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_AUTO)
    {
      fd->sched_kind = OMP_CLAUSE_SCHEDULE_STATIC;
      gcc_assert (fd->chunk_size == NULL);
    }
  gcc_assert (fd->collapse == 1 || collapse_iter != NULL);
  if (taskloop)
    fd->sched_kind = OMP_CLAUSE_SCHEDULE_RUNTIME;
  if (fd->sched_kind == OMP_CLAUSE_SCHEDULE_RUNTIME)
    gcc_assert (fd->chunk_size == NULL);
  else if (fd->chunk_size == NULL)
    {
      /* We only need to compute a default chunk size for ordered
	 static loops and dynamic loops.  */
      if (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
	  || fd->have_ordered)
	fd->chunk_size = (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC)
			 ? integer_zero_node : integer_one_node;
    }

  int cnt = fd->ordered ? fd->ordered : fd->collapse;
  for (i = 0; i < cnt; i++)
    {
      if (i == 0 && fd->collapse == 1 && (fd->ordered == 0 || loops == NULL))
	loop = &fd->loop;
      else if (loops != NULL)
	loop = loops + i;
      else
	loop = &dummy_loop;

      loop->v = gimple_omp_for_index (for_stmt, i);
      gcc_assert (SSA_VAR_P (loop->v));
      gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
		  || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
      var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
      loop->n1 = gimple_omp_for_initial (for_stmt, i);

      loop->cond_code = gimple_omp_for_cond (for_stmt, i);
      loop->n2 = gimple_omp_for_final (for_stmt, i);
      gcc_assert (loop->cond_code != NE_EXPR
		  || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKSIMD
		  || gimple_omp_for_kind (for_stmt) == GF_OMP_FOR_KIND_CILKFOR);
      omp_adjust_for_condition (loc, &loop->cond_code, &loop->n2);

      t = gimple_omp_for_incr (for_stmt, i);
      gcc_assert (TREE_OPERAND (t, 0) == var);
      loop->step = omp_get_for_step_from_incr (loc, t);

      if (simd
	  || (fd->sched_kind == OMP_CLAUSE_SCHEDULE_STATIC
	      && !fd->have_ordered))
	{
	  if (fd->collapse == 1)
	    iter_type = TREE_TYPE (loop->v);
	  else if (i == 0
		   || TYPE_PRECISION (iter_type)
		      < TYPE_PRECISION (TREE_TYPE (loop->v)))
	    iter_type
	      = build_nonstandard_integer_type
		  (TYPE_PRECISION (TREE_TYPE (loop->v)), 1);
	}
      else if (iter_type != long_long_unsigned_type_node)
	{
	  if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
	    iter_type = long_long_unsigned_type_node;
	  else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
		   && TYPE_PRECISION (TREE_TYPE (loop->v))
		      >= TYPE_PRECISION (iter_type))
	    {
	      tree n;

	      if (loop->cond_code == LT_EXPR)
		n = fold_build2_loc (loc,
				 PLUS_EXPR, TREE_TYPE (loop->v),
				 loop->n2, loop->step);
	      else
		n = loop->n1;
	      if (TREE_CODE (n) != INTEGER_CST
		  || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
		iter_type = long_long_unsigned_type_node;
	    }
	  else if (TYPE_PRECISION (TREE_TYPE (loop->v))
		   > TYPE_PRECISION (iter_type))
	    {
	      tree n1, n2;

	      if (loop->cond_code == LT_EXPR)
		{
		  n1 = loop->n1;
		  n2 = fold_build2_loc (loc,
				    PLUS_EXPR, TREE_TYPE (loop->v),
				    loop->n2, loop->step);
		}
	      else
		{
		  n1 = fold_build2_loc (loc,
				    MINUS_EXPR, TREE_TYPE (loop->v),
				    loop->n2, loop->step);
		  n2 = loop->n1;
		}
	      if (TREE_CODE (n1) != INTEGER_CST
		  || TREE_CODE (n2) != INTEGER_CST
		  || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
		  || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
		iter_type = long_long_unsigned_type_node;
	    }
	}

      if (i >= fd->collapse)
	continue;

      if (collapse_count && *collapse_count == NULL)
	{
	  t = fold_binary (loop->cond_code, boolean_type_node,
			   fold_convert (TREE_TYPE (loop->v), loop->n1),
			   fold_convert (TREE_TYPE (loop->v), loop->n2));
	  if (t && integer_zerop (t))
	    count = build_zero_cst (long_long_unsigned_type_node);
	  else if ((i == 0 || count != NULL_TREE)
		   && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
		   && TREE_CONSTANT (loop->n1)
		   && TREE_CONSTANT (loop->n2)
		   && TREE_CODE (loop->step) == INTEGER_CST)
	    {
	      tree itype = TREE_TYPE (loop->v);

	      if (POINTER_TYPE_P (itype))
		itype = signed_type_for (itype);
	      t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
	      t = fold_build2_loc (loc,
			       PLUS_EXPR, itype,
			       fold_convert_loc (loc, itype, loop->step), t);
	      t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
			       fold_convert_loc (loc, itype, loop->n2));
	      t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
			       fold_convert_loc (loc, itype, loop->n1));
	      if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
		t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
				 fold_build1_loc (loc, NEGATE_EXPR, itype, t),
				 fold_build1_loc (loc, NEGATE_EXPR, itype,
					      fold_convert_loc (loc, itype,
								loop->step)));
	      else
		t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
				 fold_convert_loc (loc, itype, loop->step));
	      t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
	      if (count != NULL_TREE)
		count = fold_build2_loc (loc,
				     MULT_EXPR, long_long_unsigned_type_node,
				     count, t);
	      else
		count = t;
	      if (TREE_CODE (count) != INTEGER_CST)
		count = NULL_TREE;
	    }
	  else if (count && !integer_zerop (count))
	    count = NULL_TREE;
	}
    }

  if (count
      && !simd
      && (fd->sched_kind != OMP_CLAUSE_SCHEDULE_STATIC
	  || fd->have_ordered))
    {
      if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
	iter_type = long_long_unsigned_type_node;
      else
	iter_type = long_integer_type_node;
    }
  else if (collapse_iter && *collapse_iter != NULL)
    iter_type = TREE_TYPE (*collapse_iter);
  fd->iter_type = iter_type;
  if (collapse_iter && *collapse_iter == NULL)
    *collapse_iter = create_tmp_var (iter_type, ".iter");
  if (collapse_count && *collapse_count == NULL)
    {
      if (count)
	*collapse_count = fold_convert_loc (loc, iter_type, count);
      else
	*collapse_count = create_tmp_var (iter_type, ".count");
    }

  if (fd->collapse > 1 || (fd->ordered && loops))
    {
      fd->loop.v = *collapse_iter;
      fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
      fd->loop.n2 = *collapse_count;
      fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
      fd->loop.cond_code = LT_EXPR;
    }
  else if (loops)
    loops[0] = fd->loop;
}
コード例 #21
0
ファイル: gimple-expr.c プロジェクト: WojciechMigda/gcc
bool
useless_type_conversion_p (tree outer_type, tree inner_type)
{
  /* Do the following before stripping toplevel qualifiers.  */
  if (POINTER_TYPE_P (inner_type)
      && POINTER_TYPE_P (outer_type))
    {
      /* Do not lose casts between pointers to different address spaces.  */
      if (TYPE_ADDR_SPACE (TREE_TYPE (outer_type))
	  != TYPE_ADDR_SPACE (TREE_TYPE (inner_type)))
	return false;
      /* Do not lose casts to function pointer types.  */
      if ((TREE_CODE (TREE_TYPE (outer_type)) == FUNCTION_TYPE
	   || TREE_CODE (TREE_TYPE (outer_type)) == METHOD_TYPE)
	  && !(TREE_CODE (TREE_TYPE (inner_type)) == FUNCTION_TYPE
	       || TREE_CODE (TREE_TYPE (inner_type)) == METHOD_TYPE))
	return false;
    }

  /* From now on qualifiers on value types do not matter.  */
  inner_type = TYPE_MAIN_VARIANT (inner_type);
  outer_type = TYPE_MAIN_VARIANT (outer_type);

  if (inner_type == outer_type)
    return true;

  /* Changes in machine mode are never useless conversions because the RTL
     middle-end expects explicit conversions between modes.  */
  if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type))
    return false;

  /* If both the inner and outer types are integral types, then the
     conversion is not necessary if they have the same mode and
     signedness and precision, and both or neither are boolean.  */
  if (INTEGRAL_TYPE_P (inner_type)
      && INTEGRAL_TYPE_P (outer_type))
    {
      /* Preserve changes in signedness or precision.  */
      if (TYPE_UNSIGNED (inner_type) != TYPE_UNSIGNED (outer_type)
	  || TYPE_PRECISION (inner_type) != TYPE_PRECISION (outer_type))
	return false;

      /* Preserve conversions to/from BOOLEAN_TYPE if types are not
	 of precision one.  */
      if (((TREE_CODE (inner_type) == BOOLEAN_TYPE)
	   != (TREE_CODE (outer_type) == BOOLEAN_TYPE))
	  && TYPE_PRECISION (outer_type) != 1)
	return false;

      /* We don't need to preserve changes in the types minimum or
	 maximum value in general as these do not generate code
	 unless the types precisions are different.  */
      return true;
    }

  /* Scalar floating point types with the same mode are compatible.  */
  else if (SCALAR_FLOAT_TYPE_P (inner_type)
	   && SCALAR_FLOAT_TYPE_P (outer_type))
    return true;

  /* Fixed point types with the same mode are compatible.  */
  else if (FIXED_POINT_TYPE_P (inner_type)
	   && FIXED_POINT_TYPE_P (outer_type))
    return true;

  /* We need to take special care recursing to pointed-to types.  */
  else if (POINTER_TYPE_P (inner_type)
	   && POINTER_TYPE_P (outer_type))
    {
      /* We do not care for const qualification of the pointed-to types
	 as const qualification has no semantic value to the middle-end.  */

      /* Otherwise pointers/references are equivalent.  */
      return true;
    }

  /* Recurse for complex types.  */
  else if (TREE_CODE (inner_type) == COMPLEX_TYPE
	   && TREE_CODE (outer_type) == COMPLEX_TYPE)
    return useless_type_conversion_p (TREE_TYPE (outer_type),
				      TREE_TYPE (inner_type));

  /* Recurse for vector types with the same number of subparts.  */
  else if (TREE_CODE (inner_type) == VECTOR_TYPE
	   && TREE_CODE (outer_type) == VECTOR_TYPE
	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
    return useless_type_conversion_p (TREE_TYPE (outer_type),
				      TREE_TYPE (inner_type));

  else if (TREE_CODE (inner_type) == ARRAY_TYPE
	   && TREE_CODE (outer_type) == ARRAY_TYPE)
    {
      /* Preserve various attributes.  */
      if (TYPE_REVERSE_STORAGE_ORDER (inner_type)
	  != TYPE_REVERSE_STORAGE_ORDER (outer_type))
	return false;
      if (TYPE_STRING_FLAG (inner_type) != TYPE_STRING_FLAG (outer_type))
	return false;

      /* Conversions from array types with unknown extent to
	 array types with known extent are not useless.  */
      if (!TYPE_DOMAIN (inner_type) && TYPE_DOMAIN (outer_type))
	return false;

      /* Nor are conversions from array types with non-constant size to
         array types with constant size or to different size.  */
      if (TYPE_SIZE (outer_type)
	  && TREE_CODE (TYPE_SIZE (outer_type)) == INTEGER_CST
	  && (!TYPE_SIZE (inner_type)
	      || TREE_CODE (TYPE_SIZE (inner_type)) != INTEGER_CST
	      || !tree_int_cst_equal (TYPE_SIZE (outer_type),
				      TYPE_SIZE (inner_type))))
	return false;

      /* Check conversions between arrays with partially known extents.
	 If the array min/max values are constant they have to match.
	 Otherwise allow conversions to unknown and variable extents.
	 In particular this declares conversions that may change the
	 mode to BLKmode as useless.  */
      if (TYPE_DOMAIN (inner_type)
	  && TYPE_DOMAIN (outer_type)
	  && TYPE_DOMAIN (inner_type) != TYPE_DOMAIN (outer_type))
	{
	  tree inner_min = TYPE_MIN_VALUE (TYPE_DOMAIN (inner_type));
	  tree outer_min = TYPE_MIN_VALUE (TYPE_DOMAIN (outer_type));
	  tree inner_max = TYPE_MAX_VALUE (TYPE_DOMAIN (inner_type));
	  tree outer_max = TYPE_MAX_VALUE (TYPE_DOMAIN (outer_type));

	  /* After gimplification a variable min/max value carries no
	     additional information compared to a NULL value.  All that
	     matters has been lowered to be part of the IL.  */
	  if (inner_min && TREE_CODE (inner_min) != INTEGER_CST)
	    inner_min = NULL_TREE;
	  if (outer_min && TREE_CODE (outer_min) != INTEGER_CST)
	    outer_min = NULL_TREE;
	  if (inner_max && TREE_CODE (inner_max) != INTEGER_CST)
	    inner_max = NULL_TREE;
	  if (outer_max && TREE_CODE (outer_max) != INTEGER_CST)
	    outer_max = NULL_TREE;

	  /* Conversions NULL / variable <- cst are useless, but not
	     the other way around.  */
	  if (outer_min
	      && (!inner_min
		  || !tree_int_cst_equal (inner_min, outer_min)))
	    return false;
	  if (outer_max
	      && (!inner_max
		  || !tree_int_cst_equal (inner_max, outer_max)))
	    return false;
	}

      /* Recurse on the element check.  */
      return useless_type_conversion_p (TREE_TYPE (outer_type),
					TREE_TYPE (inner_type));
    }

  else if ((TREE_CODE (inner_type) == FUNCTION_TYPE
	    || TREE_CODE (inner_type) == METHOD_TYPE)
	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
    {
      tree outer_parm, inner_parm;

      /* If the return types are not compatible bail out.  */
      if (!useless_type_conversion_p (TREE_TYPE (outer_type),
				      TREE_TYPE (inner_type)))
	return false;

      /* Method types should belong to a compatible base class.  */
      if (TREE_CODE (inner_type) == METHOD_TYPE
	  && !useless_type_conversion_p (TYPE_METHOD_BASETYPE (outer_type),
					 TYPE_METHOD_BASETYPE (inner_type)))
	return false;

      /* A conversion to an unprototyped argument list is ok.  */
      if (!prototype_p (outer_type))
	return true;

      /* If the unqualified argument types are compatible the conversion
	 is useless.  */
      if (TYPE_ARG_TYPES (outer_type) == TYPE_ARG_TYPES (inner_type))
	return true;

      for (outer_parm = TYPE_ARG_TYPES (outer_type),
	   inner_parm = TYPE_ARG_TYPES (inner_type);
	   outer_parm && inner_parm;
	   outer_parm = TREE_CHAIN (outer_parm),
	   inner_parm = TREE_CHAIN (inner_parm))
	if (!useless_type_conversion_p
	       (TYPE_MAIN_VARIANT (TREE_VALUE (outer_parm)),
		TYPE_MAIN_VARIANT (TREE_VALUE (inner_parm))))
	  return false;

      /* If there is a mismatch in the number of arguments the functions
	 are not compatible.  */
      if (outer_parm || inner_parm)
	return false;

      /* Defer to the target if necessary.  */
      if (TYPE_ATTRIBUTES (inner_type) || TYPE_ATTRIBUTES (outer_type))
	return comp_type_attributes (outer_type, inner_type) != 0;

      return true;
    }

  /* For aggregates we rely on TYPE_CANONICAL exclusively and require
     explicit conversions for types involving to be structurally
     compared types.  */
  else if (AGGREGATE_TYPE_P (inner_type)
	   && TREE_CODE (inner_type) == TREE_CODE (outer_type))
    return TYPE_CANONICAL (inner_type)
	   && TYPE_CANONICAL (inner_type) == TYPE_CANONICAL (outer_type);

  else if (TREE_CODE (inner_type) == OFFSET_TYPE
	   && TREE_CODE (outer_type) == OFFSET_TYPE)
    return useless_type_conversion_p (TREE_TYPE (outer_type),
				      TREE_TYPE (inner_type))
	   && useless_type_conversion_p
	        (TYPE_OFFSET_BASETYPE (outer_type),
		 TYPE_OFFSET_BASETYPE (inner_type));

  return false;
}
コード例 #22
0
ファイル: c-ubsan.c プロジェクト: Phobos37/gcc
tree
ubsan_instrument_division (location_t loc, tree op0, tree op1)
{
  tree t, tt;
  tree type = TREE_TYPE (op0);

  /* At this point both operands should have the same type,
     because they are already converted to RESULT_TYPE.
     Use TYPE_MAIN_VARIANT since typedefs can confuse us.  */
  gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (op0))
	      == TYPE_MAIN_VARIANT (TREE_TYPE (op1)));

  if (TREE_CODE (type) == INTEGER_TYPE
      && (flag_sanitize & SANITIZE_DIVIDE))
    t = fold_build2 (EQ_EXPR, boolean_type_node,
		     op1, build_int_cst (type, 0));
  else if (TREE_CODE (type) == REAL_TYPE
	   && (flag_sanitize & SANITIZE_FLOAT_DIVIDE))
    t = fold_build2 (EQ_EXPR, boolean_type_node,
		     op1, build_real (type, dconst0));
  else
    return NULL_TREE;

  /* We check INT_MIN / -1 only for signed types.  */
  if (TREE_CODE (type) == INTEGER_TYPE
      && (flag_sanitize & SANITIZE_DIVIDE)
      && !TYPE_UNSIGNED (type))
    {
      tree x;
      tt = fold_build2 (EQ_EXPR, boolean_type_node, op1,
			build_int_cst (type, -1));
      x = fold_build2 (EQ_EXPR, boolean_type_node, op0,
		       TYPE_MIN_VALUE (type));
      x = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, x, tt);
      t = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, x);
    }

  /* If the condition was folded to 0, no need to instrument
     this expression.  */
  if (integer_zerop (t))
    return NULL_TREE;

  /* In case we have a SAVE_EXPR in a conditional context, we need to
     make sure it gets evaluated before the condition.  If the OP0 is
     an instrumented array reference, mark it as having side effects so
     it's not folded away.  */
  if (flag_sanitize & SANITIZE_BOUNDS)
    {
      tree xop0 = op0;
      while (CONVERT_EXPR_P (xop0))
	xop0 = TREE_OPERAND (xop0, 0);
      if (TREE_CODE (xop0) == ARRAY_REF)
	{
	  TREE_SIDE_EFFECTS (xop0) = 1;
	  TREE_SIDE_EFFECTS (op0) = 1;
	}
    }
  t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), op0, t);
  if (flag_sanitize_undefined_trap_on_error)
    tt = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0);
  else
    {
      tree data = ubsan_create_data ("__ubsan_overflow_data", 1, &loc,
				     ubsan_type_descriptor (type), NULL_TREE,
				     NULL_TREE);
      data = build_fold_addr_expr_loc (loc, data);
      enum built_in_function bcode
	= (flag_sanitize_recover & SANITIZE_DIVIDE)
	  ? BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW
	  : BUILT_IN_UBSAN_HANDLE_DIVREM_OVERFLOW_ABORT;
      tt = builtin_decl_explicit (bcode);
      tt = build_call_expr_loc (loc, tt, 3, data, ubsan_encode_value (op0),
				ubsan_encode_value (op1));
    }
  t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_node);

  return t;
}