void
copy_mem_ref_info (tree to, tree from)
{
  /* And the info about the original reference.  */
  TREE_SIDE_EFFECTS (to) = TREE_SIDE_EFFECTS (from);
  TREE_THIS_VOLATILE (to) = TREE_THIS_VOLATILE (from);
}
Beispiel #2
0
tree
build_stmt (enum tree_code code, ...)
{
  tree ret;
  int length, i;
  va_list p;
  bool side_effects;

  va_start (p, code);

  ret = make_node (code);
  TREE_TYPE (ret) = void_type_node;
  length = TREE_CODE_LENGTH (code);
  SET_EXPR_LOCATION (ret, input_location);

  /* TREE_SIDE_EFFECTS will already be set for statements with
     implicit side effects.  Here we make sure it is set for other
     expressions by checking whether the parameters have side
     effects.  */

  side_effects = false;
  for (i = 0; i < length; i++)
    {
      tree t = va_arg (p, tree);
      if (t && !TYPE_P (t))
	side_effects |= TREE_SIDE_EFFECTS (t);
      TREE_OPERAND (ret, i) = t;
    }

  TREE_SIDE_EFFECTS (ret) |= side_effects;

  va_end (p);
  return ret;
}
Beispiel #3
0
static void
genericize_if_stmt (tree *stmt_p)
{
  tree stmt, cond, then_, else_;
  location_t locus = EXPR_LOCATION (*stmt_p);

  stmt = *stmt_p;
  cond = IF_COND (stmt);
  then_ = THEN_CLAUSE (stmt);
  else_ = ELSE_CLAUSE (stmt);

  if (!then_)
    then_ = build_empty_stmt ();
  if (!else_)
    else_ = build_empty_stmt ();

  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
    stmt = then_;
  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
    stmt = else_;
  else
    stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
  if (CAN_HAVE_LOCATION_P (stmt) && !EXPR_HAS_LOCATION (stmt))
    SET_EXPR_LOCATION (stmt, locus);
  *stmt_p = stmt;
}
Beispiel #4
0
void
copy_ref_info (tree new_ref, tree old_ref)
{
  tree new_ptr_base = NULL_TREE;

  gcc_assert (TREE_CODE (new_ref) == MEM_REF
	      || TREE_CODE (new_ref) == TARGET_MEM_REF);

  TREE_SIDE_EFFECTS (new_ref) = TREE_SIDE_EFFECTS (old_ref);
  TREE_THIS_VOLATILE (new_ref) = TREE_THIS_VOLATILE (old_ref);

  new_ptr_base = TREE_OPERAND (new_ref, 0);

  /* We can transfer points-to information from an old pointer
     or decl base to the new one.  */
  if (new_ptr_base
      && TREE_CODE (new_ptr_base) == SSA_NAME
      && !SSA_NAME_PTR_INFO (new_ptr_base))
    {
      tree base = get_base_address (old_ref);
      if (!base)
	;
      else if ((TREE_CODE (base) == MEM_REF
		|| TREE_CODE (base) == TARGET_MEM_REF)
	       && TREE_CODE (TREE_OPERAND (base, 0)) == SSA_NAME
	       && SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)))
	{
	  struct ptr_info_def *new_pi;
	  unsigned int align, misalign;

	  duplicate_ssa_name_ptr_info
	    (new_ptr_base, SSA_NAME_PTR_INFO (TREE_OPERAND (base, 0)));
	  new_pi = SSA_NAME_PTR_INFO (new_ptr_base);
	  /* We have to be careful about transferring alignment information.  */
	  if (get_ptr_info_alignment (new_pi, &align, &misalign)
	      && TREE_CODE (old_ref) == MEM_REF
	      && !(TREE_CODE (new_ref) == TARGET_MEM_REF
		   && (TMR_INDEX2 (new_ref)
		       || (TMR_STEP (new_ref)
			   && (TREE_INT_CST_LOW (TMR_STEP (new_ref))
			       < align)))))
	    {
	      unsigned int inc = (mem_ref_offset (old_ref)
				  - mem_ref_offset (new_ref)).low;
	      adjust_ptr_info_misalignment (new_pi, inc);
	    }
	  else
	    mark_ptr_info_alignment_unknown (new_pi);
	}
      else if (TREE_CODE (base) == VAR_DECL
	       || TREE_CODE (base) == PARM_DECL
	       || TREE_CODE (base) == RESULT_DECL)
	{
	  struct ptr_info_def *pi = get_ptr_info (new_ptr_base);
	  pt_solution_set_var (&pi->pt, base);
	}
    }
}
tree
tsi_split_statement_list_before (tree_stmt_iterator *i)
{
  struct tree_statement_list_node *cur, *prev;
  tree old_sl, new_sl;

  cur = i->ptr;
  /* How can we possibly split after the end, or before the beginning?  */
  gcc_assert (cur);
  prev = cur->prev;

  old_sl = i->container;
  new_sl = alloc_stmt_list ();
  TREE_SIDE_EFFECTS (new_sl) = 1;
  i->container = new_sl;

  STATEMENT_LIST_HEAD (new_sl) = cur;
  STATEMENT_LIST_TAIL (new_sl) = STATEMENT_LIST_TAIL (old_sl);
  STATEMENT_LIST_TAIL (old_sl) = prev;
  cur->prev = NULL;
  if (prev)
    prev->next = NULL;
  else
    STATEMENT_LIST_HEAD (old_sl) = NULL;

  return new_sl;
}
Beispiel #6
0
static inline void
unpack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
{
  /* Note that the code for EXPR has already been unpacked to create EXPR in
     streamer_alloc_tree.  */
  if (!TYPE_P (expr))
    {
      TREE_SIDE_EFFECTS (expr) = (unsigned) bp_unpack_value (bp, 1);
      TREE_CONSTANT (expr) = (unsigned) bp_unpack_value (bp, 1);
      TREE_READONLY (expr) = (unsigned) bp_unpack_value (bp, 1);

      /* TREE_PUBLIC is used on types to indicate that the type
	 has a TYPE_CACHED_VALUES vector.  This is not streamed out,
	 so we skip it here.  */
      TREE_PUBLIC (expr) = (unsigned) bp_unpack_value (bp, 1);
    }
  else
    bp_unpack_value (bp, 4);
  TREE_ADDRESSABLE (expr) = (unsigned) bp_unpack_value (bp, 1);
  TREE_THIS_VOLATILE (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (DECL_P (expr))
    DECL_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
  else if (TYPE_P (expr))
    TYPE_UNSIGNED (expr) = (unsigned) bp_unpack_value (bp, 1);
  else
    bp_unpack_value (bp, 1);
  TREE_ASM_WRITTEN (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (TYPE_P (expr))
    TYPE_ARTIFICIAL (expr) = (unsigned) bp_unpack_value (bp, 1);
  else
    TREE_NO_WARNING (expr) = (unsigned) bp_unpack_value (bp, 1);
  TREE_NOTHROW (expr) = (unsigned) bp_unpack_value (bp, 1);
  TREE_STATIC (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (TREE_CODE (expr) != TREE_BINFO)
    TREE_PRIVATE (expr) = (unsigned) bp_unpack_value (bp, 1);
  else
    bp_unpack_value (bp, 1);
  TREE_PROTECTED (expr) = (unsigned) bp_unpack_value (bp, 1);
  TREE_DEPRECATED (expr) = (unsigned) bp_unpack_value (bp, 1);
  if (TYPE_P (expr))
    {
      if (AGGREGATE_TYPE_P (expr))
	TYPE_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
      else
	TYPE_SATURATING (expr) = (unsigned) bp_unpack_value (bp, 1);
      TYPE_ADDR_SPACE (expr) = (unsigned) bp_unpack_value (bp, 8);
    }
  else if (TREE_CODE (expr) == BIT_FIELD_REF || TREE_CODE (expr) == MEM_REF)
    {
      REF_REVERSE_STORAGE_ORDER (expr) = (unsigned) bp_unpack_value (bp, 1);
      bp_unpack_value (bp, 8);
    }
  else if (TREE_CODE (expr) == SSA_NAME)
    {
      SSA_NAME_IS_DEFAULT_DEF (expr) = (unsigned) bp_unpack_value (bp, 1);
      bp_unpack_value (bp, 8);
    }
  else
    bp_unpack_value (bp, 9);
}
static void
gimplify_expr_stmt (tree *stmt_p)
{
  tree stmt = EXPR_STMT_EXPR (*stmt_p);

  if (stmt == error_mark_node)
    stmt = NULL;

  /* Gimplification of a statement expression will nullify the
     statement if all its side effects are moved to *PRE_P and *POST_P.

     In this case we will not want to emit the gimplified statement.
     However, we may still want to emit a warning, so we do that before
     gimplification.  */
  if (stmt && (extra_warnings || warn_unused_value))
    {
      if (!TREE_SIDE_EFFECTS (stmt))
	{
	  if (!IS_EMPTY_STMT (stmt)
	      && !VOID_TYPE_P (TREE_TYPE (stmt))
	      && !TREE_NO_WARNING (stmt))
	    warning (0, "statement with no effect");
	}
      else if (warn_unused_value)
	warn_if_unused_value (stmt, input_location);
    }

  if (stmt == NULL_TREE)
    stmt = alloc_stmt_list ();

  *stmt_p = stmt;
}
Beispiel #8
0
tree
c_build_bind_expr (tree block, tree body)
{
  tree decls, bind;

  if (block == NULL_TREE)
    decls = NULL_TREE;
  else if (TREE_CODE (block) == BLOCK)
    decls = BLOCK_VARS (block);
  else
    {
      decls = block;
      if (DECL_ARTIFICIAL (decls))
        block = NULL_TREE;
      else
        {
          block = make_node (BLOCK);
          BLOCK_VARS (block) = decls;
          add_block_to_enclosing (block);
        }
    }

  if (!body)
    body = build_empty_stmt ();
  if (decls || block)
    {
      bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
      TREE_SIDE_EFFECTS (bind) = 1;
    }
  else
    bind = body;

  return bind;
}
Beispiel #9
0
void
recalculate_side_effects (tree t)
{
  enum tree_code code = TREE_CODE (t);
  int len = TREE_CODE_LENGTH (code);
  int i;

  switch (TREE_CODE_CLASS (code))
    {
    case tcc_expression:
      switch (code)
	{
	case INIT_EXPR:
	case MODIFY_EXPR:
	case VA_ARG_EXPR:
	case PREDECREMENT_EXPR:
	case PREINCREMENT_EXPR:
	case POSTDECREMENT_EXPR:
	case POSTINCREMENT_EXPR:
	  /* All of these have side-effects, no matter what their
	     operands are.  */
	  return;

	default:
	  break;
	}
      /* Fall through.  */

    case tcc_comparison:  /* a comparison expression */
    case tcc_unary:       /* a unary arithmetic expression */
    case tcc_binary:      /* a binary arithmetic expression */
    case tcc_reference:   /* a reference */
      TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t);
      for (i = 0; i < len; ++i)
	{
	  tree op = TREE_OPERAND (t, i);
	  if (op && TREE_SIDE_EFFECTS (op))
	    TREE_SIDE_EFFECTS (t) = 1;
	}
      break;

    default:
      /* Can never be used with non-expressions.  */
      gcc_unreachable ();
   }
}
Beispiel #10
0
static void
append_stmt (tree stmt)
{
  if (!EXPR_HAS_LOCATION (stmt))
    SET_EXPR_LOCATION (stmt, input_location);
  TREE_SIDE_EFFECTS (stmt) = true;
  append_to_statement_list (stmt, &cur_stmts);
}
Beispiel #11
0
void 
tree_code_output_expression_statement (tree code, 
                                       unsigned char* filename, int lineno)
{
  /* Output the line number information.  */
  emit_line_note ((const char *)filename, lineno); 
  TREE_USED (code) = 1;
  TREE_SIDE_EFFECTS (code) = 1;
  expand_expr_stmt (code);
}
Beispiel #12
0
static bool
nonpure_call_p (tree stmt)
{
  tree call = get_call_expr_in (stmt);

  if (!call)
    return false;

  return TREE_SIDE_EFFECTS (call) != 0;
}
Beispiel #13
0
tree
convert_from_reference (tree val)
{
  if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
    {
      tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val)));
      tree ref = build1 (INDIRECT_REF, t, val);

       /* We *must* set TREE_READONLY when dereferencing a pointer to const,
	  so that we get the proper error message if the result is used
	  to assign to.  Also, &* is supposed to be a no-op.  */
      TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
      TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
      TREE_SIDE_EFFECTS (ref)
	= (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
      REFERENCE_REF_P (ref) = 1;
      val = ref;
    }

  return val;
}
/* Callback for walk_stmt_load_store_ops.

   Return TRUE if OP will dereference the tree stored in DATA, FALSE
   otherwise.

   This routine only makes a superficial check for a dereference.  Thus,
   it must only be used if it is safe to return a false negative.  */
static bool
check_loadstore (gimple stmt, tree op, tree, void *data)
{
  if ((TREE_CODE (op) == MEM_REF || TREE_CODE (op) == TARGET_MEM_REF)
      && operand_equal_p (TREE_OPERAND (op, 0), (tree)data, 0))
    {
      TREE_THIS_VOLATILE (op) = 1;
      TREE_SIDE_EFFECTS (op) = 1;
      update_stmt (stmt);
      return true;
    }
  return false;
}
static void
gimplify_if_stmt (tree *stmt_p)
{
  tree stmt, cond, then_, else_;

  stmt = *stmt_p;
  cond = IF_COND (stmt);
  then_ = THEN_CLAUSE (stmt);
  else_ = ELSE_CLAUSE (stmt);

  if (!then_)
    then_ = build_empty_stmt ();
  if (!else_)
    else_ = build_empty_stmt ();

  if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
    stmt = then_;
  else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
    stmt = else_;
  else
    stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
  *stmt_p = stmt;
}
Beispiel #16
0
tree
build_stmt (location_t loc, enum tree_code code, ...)
{
  tree ret;
  int length, i;
  va_list p;
  bool side_effects;

  /* This function cannot be used to construct variably-sized nodes.  */
  gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp);

  va_start (p, code);

  ret = make_node (code);
  TREE_TYPE (ret) = void_type_node;
  length = TREE_CODE_LENGTH (code);
  SET_EXPR_LOCATION (ret, loc);

  /* TREE_SIDE_EFFECTS will already be set for statements with
     implicit side effects.  Here we make sure it is set for other
     expressions by checking whether the parameters have side
     effects.  */

  side_effects = false;
  for (i = 0; i < length; i++)
    {
      tree t = va_arg (p, tree);
      if (t && !TYPE_P (t))
	side_effects |= TREE_SIDE_EFFECTS (t);
      TREE_OPERAND (ret, i) = t;
    }

  TREE_SIDE_EFFECTS (ret) |= side_effects;

  va_end (p);
  return ret;
}
Beispiel #17
0
static void
pack_ts_base_value_fields (struct bitpack_d *bp, tree expr)
{
  bp_pack_value (bp, TREE_CODE (expr), 16);
  if (!TYPE_P (expr))
    {
      bp_pack_value (bp, TREE_SIDE_EFFECTS (expr), 1);
      bp_pack_value (bp, TREE_CONSTANT (expr), 1);
      bp_pack_value (bp, TREE_READONLY (expr), 1);

      /* TREE_PUBLIC is used on types to indicate that the type
	 has a TYPE_CACHED_VALUES vector.  This is not streamed out,
	 so we skip it here.  */
      bp_pack_value (bp, TREE_PUBLIC (expr), 1);
    }
  else
    bp_pack_value (bp, 0, 4);
  bp_pack_value (bp, TREE_ADDRESSABLE (expr), 1);
  bp_pack_value (bp, TREE_THIS_VOLATILE (expr), 1);
  if (DECL_P (expr))
    bp_pack_value (bp, DECL_UNSIGNED (expr), 1);
  else if (TYPE_P (expr))
    bp_pack_value (bp, TYPE_UNSIGNED (expr), 1);
  else
    bp_pack_value (bp, 0, 1);
  /* We write debug info two times, do not confuse the second one.
     The only relevant TREE_ASM_WRITTEN use is on SSA names.  */
  bp_pack_value (bp, (TREE_CODE (expr) != SSA_NAME
		      ? 0 : TREE_ASM_WRITTEN (expr)), 1);
  if (TYPE_P (expr))
    bp_pack_value (bp, TYPE_ARTIFICIAL (expr), 1);
  else
    bp_pack_value (bp, TREE_NO_WARNING (expr), 1);
  bp_pack_value (bp, TREE_NOTHROW (expr), 1);
  bp_pack_value (bp, TREE_STATIC (expr), 1);
  if (TREE_CODE (expr) != TREE_BINFO)
    bp_pack_value (bp, TREE_PRIVATE (expr), 1);
  bp_pack_value (bp, TREE_PROTECTED (expr), 1);
  bp_pack_value (bp, TREE_DEPRECATED (expr), 1);
  if (TYPE_P (expr))
    {
      bp_pack_value (bp, TYPE_SATURATING (expr), 1);
      bp_pack_value (bp, TYPE_ADDR_SPACE (expr), 8);
    }
  else if (TREE_CODE (expr) == SSA_NAME)
    bp_pack_value (bp, SSA_NAME_IS_DEFAULT_DEF (expr), 1);
  else
    bp_pack_value (bp, 0, 1);
}
Beispiel #18
0
static void
push_binding (void)
{
  struct binding_level *res;

  if (old_binding_levels == NULL)
	  /*
	   * This looks like a normal memory allocation, so
	   * gcc_alloc changed to xmalloc
	   */
    res = (struct binding_level *) xmalloc (sizeof (struct binding_level));
  else
    {
      res = old_binding_levels;
      old_binding_levels = res->prev;
    }

  /* Init.  */
  res->first_decl = NULL_TREE;
  res->last_decl = NULL_TREE;

  res->first_block = NULL_TREE;
  res->last_block = NULL_TREE;

  res->save_stack = 0;

  res->bind = make_node (BIND_EXPR);
  res->block = make_node (BLOCK);
  BIND_EXPR_BLOCK (res->bind) = res->block;
  TREE_SIDE_EFFECTS (res->bind) = true;
  TREE_TYPE (res->bind) = void_type_node;
  TREE_USED (res->block) = true;

  if (cur_binding_level != NULL)
    {
      /* Append the block created.  */
      if (cur_binding_level->first_block == NULL)
	cur_binding_level->first_block = res->block;
      else
	TREE_CHAIN (cur_binding_level->last_block) = res->block;
      cur_binding_level->last_block = res->block;

      BLOCK_SUPERCONTEXT (res->block) = cur_binding_level->block;
    }

  res->prev = cur_binding_level;
  cur_binding_level = res;
}
Beispiel #19
0
tree
build_dynamic_cast (tree type, tree expr)
{
  if (type == error_mark_node || expr == error_mark_node)
    return error_mark_node;
  
  if (processing_template_decl)
    {
      expr = build_min (DYNAMIC_CAST_EXPR, type, expr);
      TREE_SIDE_EFFECTS (expr) = 1;
      
      return expr;
    }

  return convert_from_reference (build_dynamic_cast_1 (type, expr));
}
Beispiel #20
0
tree
pop_stmt_list (tree t)
{
  tree u = NULL_TREE;

  /* Pop statement lists until we reach the target level.  The extra
     nestings will be due to outstanding cleanups.  */
  while (1)
    {
      u = stmt_list_stack->pop ();
      if (!stmt_list_stack->is_empty ())
	{
	  tree x = stmt_list_stack->last ();
	  STATEMENT_LIST_HAS_LABEL (x) |= STATEMENT_LIST_HAS_LABEL (u);
	}
      if (t == u)
	break;
    }

  gcc_assert (u != NULL_TREE);

  /* If the statement list is completely empty, just return it.  This is
     just as good small as build_empty_stmt, with the advantage that
     statement lists are merged when they appended to one another.  So
     using the STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P
     statements.  */
  if (TREE_SIDE_EFFECTS (t))
    {
      tree_stmt_iterator i = tsi_start (t);

      /* If the statement list contained exactly one statement, then
	 extract it immediately.  */
      if (tsi_one_before_end_p (i))
	{
	  u = tsi_stmt (i);
	  tsi_delink (&i);
	  free_stmt_list (t);
	  t = u;
	}
    }

  return t;
}
Beispiel #21
0
bool
is_gimple_reg_rhs (tree t)
{
  /* If the RHS of the MODIFY_EXPR may throw or make a nonlocal goto
     and the LHS is a user variable, then we need to introduce a formal
     temporary.  This way the optimizers can determine that the user
     variable is only modified if evaluation of the RHS does not throw.

     Don't force a temp of a non-renamable type; the copy could be
     arbitrarily expensive.  Instead we will generate a V_MAY_DEF for
     the assignment.  */

  if (is_gimple_reg_type (TREE_TYPE (t))
      && ((TREE_CODE (t) == CALL_EXPR && TREE_SIDE_EFFECTS (t))
	  || tree_could_throw_p (t)))
    return false;

  return is_gimple_formal_tmp_rhs (t);
}
Beispiel #22
0
tree
begin_eh_spec_block (void)
{
  tree r;
  location_t spec_location = DECL_SOURCE_LOCATION (current_function_decl);

  /* A noexcept specification (or throw() with -fnothrow-opt) is a
     MUST_NOT_THROW_EXPR.  */
  if (TYPE_NOEXCEPT_P (TREE_TYPE (current_function_decl)))
    {
      r = build_stmt (spec_location, MUST_NOT_THROW_EXPR,
		      NULL_TREE, NULL_TREE);
      TREE_SIDE_EFFECTS (r) = 1;
    }
  else
    r = build_stmt (spec_location, EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
  add_stmt (r);
  TREE_OPERAND (r, 0) = push_stmt_list ();
  return r;
}
Beispiel #23
0
static tree
cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr,
			  enum ubsan_null_ckind ckind)
{
  type = TYPE_MAIN_VARIANT (type);
  const char *mangled = mangle_type_string (type);
  hashval_t str_hash1 = htab_hash_string (mangled);
  hashval_t str_hash2 = iterative_hash (mangled, strlen (mangled), 0);
  tree str_hash = wide_int_to_tree (uint64_type_node,
				    wi::uhwi (((uint64_t) str_hash1 << 32)
					      | str_hash2, 64));
  if (!is_addr)
    op = build_fold_addr_expr_loc (loc, op);
  op = save_expr (op);
  tree vptr = fold_build3_loc (loc, COMPONENT_REF,
			       TREE_TYPE (TYPE_VFIELD (type)),
			       build_fold_indirect_ref_loc (loc, op),
			       TYPE_VFIELD (type), NULL_TREE);
  vptr = fold_convert_loc (loc, pointer_sized_int_node, vptr);
  vptr = fold_convert_loc (loc, uint64_type_node, vptr);
  if (ckind == UBSAN_DOWNCAST_POINTER)
    {
      tree cond = build2_loc (loc, NE_EXPR, boolean_type_node, op,
			      build_zero_cst (TREE_TYPE (op)));
      /* This is a compiler generated comparison, don't emit
	 e.g. -Wnonnull-compare warning for it.  */
      TREE_NO_WARNING (cond) = 1;
      vptr = build3_loc (loc, COND_EXPR, uint64_type_node, cond,
			 vptr, build_int_cst (uint64_type_node, 0));
    }
  tree ti_decl = get_tinfo_decl (type);
  mark_used (ti_decl);
  tree ptype = build_pointer_type (type);
  tree call
    = build_call_expr_internal_loc (loc, IFN_UBSAN_VPTR,
				    void_type_node, 5, op, vptr, str_hash,
				    build_address (ti_decl),
				    build_int_cst (ptype, ckind));
  TREE_SIDE_EFFECTS (call) = 1;
  return fold_build2 (COMPOUND_EXPR, TREE_TYPE (op), call, op);
}
void
tsi_delink (tree_stmt_iterator *i)
{
  struct tree_statement_list_node *cur, *next, *prev;

  cur = i->ptr;
  next = cur->next;
  prev = cur->prev;

  if (prev)
    prev->next = next;
  else
    STATEMENT_LIST_HEAD (i->container) = next;
  if (next)
    next->prev = prev;
  else
    STATEMENT_LIST_TAIL (i->container) = prev;

  if (!next && !prev)
    TREE_SIDE_EFFECTS (i->container) = 0;

  i->ptr = next;
}
Beispiel #25
0
bool
cilk_detect_spawn_and_unwrap (tree *exp0)
{
  tree exp = *exp0;

  if (!TREE_SIDE_EFFECTS (exp))
    return false;

  /* Strip off any conversion to void.  It does not affect whether spawn 
     is supported here.  */
  if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp)))
    exp = TREE_OPERAND (exp, 0);

  if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR)
    exp = TREE_OPERAND (exp, 1);

  while (cilk_ignorable_spawn_rhs_op (exp))
    exp = TREE_OPERAND (exp, 0);

  if (TREE_CODE (exp) == TARGET_EXPR)
    if (TARGET_EXPR_INITIAL (exp)
	&& TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR)
      exp = TARGET_EXPR_INITIAL (exp);

  /* Happens with C++ TARGET_EXPR.  */
  if (exp == NULL_TREE)
    return false;

  while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT)
    exp = TREE_OPERAND (exp, 0);
  
  /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around 
     it, or return false.  */
  if (recognize_spawn (exp, exp0))
    return true;
  return false;
}
Beispiel #26
0
void
tree_code_generate_return (tree type, tree exp)
{
  tree setret;
  tree param;

  for (param = DECL_ARGUMENTS (current_function_decl);
       param;
       param = TREE_CHAIN (param))
    {
      if (DECL_CONTEXT (param) != current_function_decl)
        abort ();
    }

  if (exp)
    {
      setret = build (MODIFY_EXPR, type, DECL_RESULT (current_function_decl), 
                     build1 (CONVERT_EXPR, type, exp));
      TREE_SIDE_EFFECTS (setret) = 1;
      TREE_USED (setret) = 1;
      expand_expr_stmt (setret);
    }
  expand_return (DECL_RESULT (current_function_decl));
}
Beispiel #27
0
static void
build_field (segment_info *h, tree union_type, record_layout_info rli)
{
  tree field;
  tree name;
  HOST_WIDE_INT offset = h->offset;
  unsigned HOST_WIDE_INT desired_align, known_align;

  name = get_identifier (h->sym->name);
  field = build_decl (h->sym->declared_at.lb->location,
		      FIELD_DECL, name, h->field);
  known_align = (offset & -offset) * BITS_PER_UNIT;
  if (known_align == 0 || known_align > BIGGEST_ALIGNMENT)
    known_align = BIGGEST_ALIGNMENT;

  desired_align = update_alignment_for_field (rli, field, known_align);
  if (desired_align > known_align)
    DECL_PACKED (field) = 1;

  DECL_FIELD_CONTEXT (field) = union_type;
  DECL_FIELD_OFFSET (field) = size_int (offset);
  DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
  SET_DECL_OFFSET_ALIGN (field, known_align);

  rli->offset = size_binop (MAX_EXPR, rli->offset,
                            size_binop (PLUS_EXPR,
                                        DECL_FIELD_OFFSET (field),
                                        DECL_SIZE_UNIT (field)));
  /* If this field is assigned to a label, we create another two variables.
     One will hold the address of target label or format label. The other will
     hold the length of format label string.  */
  if (h->sym->attr.assign)
    {
      tree len;
      tree addr;

      gfc_allocate_lang_decl (field);
      GFC_DECL_ASSIGN (field) = 1;
      len = gfc_create_var_np (gfc_charlen_type_node,h->sym->name);
      addr = gfc_create_var_np (pvoid_type_node, h->sym->name);
      TREE_STATIC (len) = 1;
      TREE_STATIC (addr) = 1;
      DECL_INITIAL (len) = build_int_cst (gfc_charlen_type_node, -2);
      gfc_set_decl_location (len, &h->sym->declared_at);
      gfc_set_decl_location (addr, &h->sym->declared_at);
      GFC_DECL_STRING_LEN (field) = pushdecl_top_level (len);
      GFC_DECL_ASSIGN_ADDR (field) = pushdecl_top_level (addr);
    }

  /* If this field is volatile, mark it.  */
  if (h->sym->attr.volatile_)
    {
      tree new_type;
      TREE_THIS_VOLATILE (field) = 1;
      TREE_SIDE_EFFECTS (field) = 1;
      new_type = build_qualified_type (TREE_TYPE (field), TYPE_QUAL_VOLATILE);
      TREE_TYPE (field) = new_type;
    }

  h->field = field;
}
Beispiel #28
0
void
do_jump (tree exp, rtx if_false_label, rtx if_true_label, int prob)
{
  enum tree_code code = TREE_CODE (exp);
  rtx temp;
  int i;
  tree type;
  enum machine_mode mode;
  rtx drop_through_label = 0;

  switch (code)
    {
    case ERROR_MARK:
      break;

    case INTEGER_CST:
      temp = integer_zerop (exp) ? if_false_label : if_true_label;
      if (temp)
        emit_jump (temp);
      break;

#if 0
      /* This is not true with #pragma weak  */
    case ADDR_EXPR:
      /* The address of something can never be zero.  */
      if (if_true_label)
        emit_jump (if_true_label);
      break;
#endif

    case NOP_EXPR:
      if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
          || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
          || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
          || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
        goto normal;
    case CONVERT_EXPR:
      /* If we are narrowing the operand, we have to do the compare in the
         narrower mode.  */
      if ((TYPE_PRECISION (TREE_TYPE (exp))
           < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
        goto normal;
    case NON_LVALUE_EXPR:
    case ABS_EXPR:
    case NEGATE_EXPR:
    case LROTATE_EXPR:
    case RROTATE_EXPR:
      /* These cannot change zero->nonzero or vice versa.  */
      do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label, prob);
      break;

    case TRUTH_NOT_EXPR:
      do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label,
	       inv (prob));
      break;

    case COND_EXPR:
      {
	rtx label1 = gen_label_rtx ();
	if (!if_true_label || !if_false_label)
	  {
	    drop_through_label = gen_label_rtx ();
	    if (!if_true_label)
	      if_true_label = drop_through_label;
	    if (!if_false_label)
	      if_false_label = drop_through_label;
	  }

        do_pending_stack_adjust ();
	do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX, -1);
	do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label, prob);
        emit_label (label1);
	do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label, prob);
	break;
      }

    case COMPOUND_EXPR:
      /* Lowered by gimplify.c.  */
      gcc_unreachable ();

    case COMPONENT_REF:
    case BIT_FIELD_REF:
    case ARRAY_REF:
    case ARRAY_RANGE_REF:
      {
        HOST_WIDE_INT bitsize, bitpos;
        int unsignedp;
        enum machine_mode mode;
        tree type;
        tree offset;
        int volatilep = 0;

        /* Get description of this reference.  We don't actually care
           about the underlying object here.  */
        get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
                             &unsignedp, &volatilep, false);

        type = lang_hooks.types.type_for_size (bitsize, unsignedp);
        if (! SLOW_BYTE_ACCESS
            && type != 0 && bitsize >= 0
            && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
            && have_insn_for (COMPARE, TYPE_MODE (type)))
          {
	    do_jump (fold_convert (type, exp), if_false_label, if_true_label,
		     prob);
            break;
          }
        goto normal;
      }

    case MINUS_EXPR:
      /* Nonzero iff operands of minus differ.  */
      code = NE_EXPR;

      /* FALLTHRU */
    case EQ_EXPR:
    case NE_EXPR:
    case LT_EXPR:
    case LE_EXPR:
    case GT_EXPR:
    case GE_EXPR:
    case ORDERED_EXPR:
    case UNORDERED_EXPR:
    case UNLT_EXPR:
    case UNLE_EXPR:
    case UNGT_EXPR:
    case UNGE_EXPR:
    case UNEQ_EXPR:
    case LTGT_EXPR:
    case TRUTH_ANDIF_EXPR:
    case TRUTH_ORIF_EXPR:
    other_code:
      do_jump_1 (code, TREE_OPERAND (exp, 0), TREE_OPERAND (exp, 1),
		 if_false_label, if_true_label, prob);
      break;

    case BIT_AND_EXPR:
      /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
	 See if the former is preferred for jump tests and restore it
	 if so.  */
      if (integer_onep (TREE_OPERAND (exp, 1)))
	{
	  tree exp0 = TREE_OPERAND (exp, 0);
	  rtx set_label, clr_label;
	  int setclr_prob = prob;

	  /* Strip narrowing integral type conversions.  */
	  while (CONVERT_EXPR_P (exp0)
		 && TREE_OPERAND (exp0, 0) != error_mark_node
		 && TYPE_PRECISION (TREE_TYPE (exp0))
		    <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
	    exp0 = TREE_OPERAND (exp0, 0);

	  /* "exp0 ^ 1" inverts the sense of the single bit test.  */
	  if (TREE_CODE (exp0) == BIT_XOR_EXPR
	      && integer_onep (TREE_OPERAND (exp0, 1)))
	    {
	      exp0 = TREE_OPERAND (exp0, 0);
	      clr_label = if_true_label;
	      set_label = if_false_label;
	      setclr_prob = inv (prob);
	    }
	  else
	    {
	      clr_label = if_false_label;
	      set_label = if_true_label;
	    }

	  if (TREE_CODE (exp0) == RSHIFT_EXPR)
	    {
	      tree arg = TREE_OPERAND (exp0, 0);
	      tree shift = TREE_OPERAND (exp0, 1);
	      tree argtype = TREE_TYPE (arg);
	      if (TREE_CODE (shift) == INTEGER_CST
		  && compare_tree_int (shift, 0) >= 0
		  && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
		  && prefer_and_bit_test (TYPE_MODE (argtype),
					  TREE_INT_CST_LOW (shift)))
		{
		  unsigned HOST_WIDE_INT mask
		    = (unsigned HOST_WIDE_INT) 1 << TREE_INT_CST_LOW (shift);
		  do_jump (build2 (BIT_AND_EXPR, argtype, arg,
				   build_int_cstu (argtype, mask)),
			   clr_label, set_label, setclr_prob);
		  break;
		}
	    }
	}

      /* If we are AND'ing with a small constant, do this comparison in the
         smallest type that fits.  If the machine doesn't have comparisons
         that small, it will be converted back to the wider comparison.
         This helps if we are testing the sign bit of a narrower object.
         combine can't do this for us because it can't know whether a
         ZERO_EXTRACT or a compare in a smaller mode exists, but we do.  */

      if (! SLOW_BYTE_ACCESS
          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
          && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
          && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
          && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
          && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
          && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
          && have_insn_for (COMPARE, TYPE_MODE (type)))
        {
	  do_jump (fold_convert (type, exp), if_false_label, if_true_label,
		   prob);
          break;
        }

      if (TYPE_PRECISION (TREE_TYPE (exp)) > 1
	  || TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
	goto normal;

      /* Boolean comparisons can be compiled as TRUTH_AND_EXPR.  */

    case TRUTH_AND_EXPR:
      /* High branch cost, expand as the bitwise AND of the conditions.
	 Do the same if the RHS has side effects, because we're effectively
	 turning a TRUTH_AND_EXPR into a TRUTH_ANDIF_EXPR.  */
      if (BRANCH_COST (optimize_insn_for_speed_p (),
		       false) >= 4
	  || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
	goto normal;
      code = TRUTH_ANDIF_EXPR;
      goto other_code;

    case BIT_IOR_EXPR:
    case TRUTH_OR_EXPR:
      /* High branch cost, expand as the bitwise OR of the conditions.
	 Do the same if the RHS has side effects, because we're effectively
	 turning a TRUTH_OR_EXPR into a TRUTH_ORIF_EXPR.  */
      if (BRANCH_COST (optimize_insn_for_speed_p (), false) >= 4
	  || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
	goto normal;
      code = TRUTH_ORIF_EXPR;
      goto other_code;

      /* Fall through and generate the normal code.  */
    default:
    normal:
      temp = expand_normal (exp);
      do_pending_stack_adjust ();
      /* The RTL optimizers prefer comparisons against pseudos.  */
      if (GET_CODE (temp) == SUBREG)
	{
	  /* Compare promoted variables in their promoted mode.  */
	  if (SUBREG_PROMOTED_VAR_P (temp)
	      && REG_P (XEXP (temp, 0)))
	    temp = XEXP (temp, 0);
	  else
	    temp = copy_to_reg (temp);
	}
      do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
			       NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
			       GET_MODE (temp), NULL_RTX,
			       if_false_label, if_true_label, prob);
    }

  if (drop_through_label)
    {
      do_pending_stack_adjust ();
      emit_label (drop_through_label);
    }
}
Beispiel #29
0
static tree
ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype,
					  enum ubsan_null_ckind ckind)
{
  if (!do_ubsan_in_current_function ())
    return NULL_TREE;

  tree type = TREE_TYPE (ptype);
  tree orig_op = op;
  bool instrument = false;
  unsigned int mina = 0;

  if (flag_sanitize & SANITIZE_ALIGNMENT)
    {
      mina = min_align_of_type (type);
      if (mina <= 1)
	mina = 0;
    }
  while ((TREE_CODE (op) == NOP_EXPR
	  || TREE_CODE (op) == NON_LVALUE_EXPR)
	 && TREE_CODE (TREE_TYPE (op)) == POINTER_TYPE)
    op = TREE_OPERAND (op, 0);
  if (TREE_CODE (op) == NOP_EXPR
      && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
    {
      if (mina && mina > min_align_of_type (TREE_TYPE (TREE_TYPE (op))))
	instrument = true;
    }
  else
    {
      if ((flag_sanitize & SANITIZE_NULL) && TREE_CODE (op) == ADDR_EXPR)
	{
	  bool strict_overflow_p = false;
	  /* tree_single_nonzero_warnv_p will not return true for non-weak
	     non-automatic decls with -fno-delete-null-pointer-checks,
	     which is disabled during -fsanitize=null.  We don't want to
	     instrument those, just weak vars though.  */
	  int save_flag_delete_null_pointer_checks
	    = flag_delete_null_pointer_checks;
	  flag_delete_null_pointer_checks = 1;
	  if (!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
	      || strict_overflow_p)
	    instrument = true;
	  flag_delete_null_pointer_checks
	    = save_flag_delete_null_pointer_checks;
	}
      else if (flag_sanitize & SANITIZE_NULL)
	instrument = true;
      if (mina && mina > 1)
	{
	  if (!POINTER_TYPE_P (TREE_TYPE (op))
	      || mina > get_pointer_alignment (op) / BITS_PER_UNIT)
	    instrument = true;
	}
    }
  if (!instrument)
    return NULL_TREE;
  op = save_expr (orig_op);
  gcc_assert (POINTER_TYPE_P (ptype));
  if (TREE_CODE (ptype) == REFERENCE_TYPE)
    ptype = build_pointer_type (TREE_TYPE (ptype));
  tree kind = build_int_cst (ptype, ckind);
  tree align = build_int_cst (pointer_sized_int_node, mina);
  tree call
    = build_call_expr_internal_loc (loc, IFN_UBSAN_NULL, void_type_node,
				    3, op, kind, align);
  TREE_SIDE_EFFECTS (call) = 1;
  return fold_build2 (COMPOUND_EXPR, TREE_TYPE (op), call, op);
}
Beispiel #30
0
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++;
            }
        }