示例#1
0
void
mark_addressable (tree x)
{
  while (handled_component_p (x))
    x = TREE_OPERAND (x, 0);
  if (TREE_CODE (x) == MEM_REF
      && TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
    x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
  if (TREE_CODE (x) != VAR_DECL
      && TREE_CODE (x) != PARM_DECL
      && TREE_CODE (x) != RESULT_DECL)
    return;
  TREE_ADDRESSABLE (x) = 1;

  /* Also mark the artificial SSA_NAME that points to the partition of X.  */
  if (TREE_CODE (x) == VAR_DECL
      && !DECL_EXTERNAL (x)
      && !TREE_STATIC (x)
      && cfun->gimple_df != NULL
      && cfun->gimple_df->decls_to_pointers != NULL)
    {
      tree *namep = cfun->gimple_df->decls_to_pointers->get (x);
      if (namep)
	TREE_ADDRESSABLE (*namep) = 1;
    }
}
示例#2
0
bool
java_mark_addressable (tree exp)
{
  tree x = exp;
  while (1)
    switch (TREE_CODE (x))
      {
      case ADDR_EXPR:
      case COMPONENT_REF:
      case ARRAY_REF:
      case REALPART_EXPR:
      case IMAGPART_EXPR:
	x = TREE_OPERAND (x, 0);
	break;

      case TRUTH_ANDIF_EXPR:
      case TRUTH_ORIF_EXPR:
      case COMPOUND_EXPR:
	x = TREE_OPERAND (x, 1);
	break;

      case COND_EXPR:
	return java_mark_addressable (TREE_OPERAND (x, 1))
	  && java_mark_addressable (TREE_OPERAND (x, 2));

      case CONSTRUCTOR:
	TREE_ADDRESSABLE (x) = 1;
	return true;

      case INDIRECT_REF:
	/* We sometimes add a cast *(TYPE*)&FOO to handle type and mode
	   incompatibility problems.  Handle this case by marking FOO.  */
	if (TREE_CODE (TREE_OPERAND (x, 0)) == NOP_EXPR
	    && TREE_CODE (TREE_OPERAND (TREE_OPERAND (x, 0), 0)) == ADDR_EXPR)
	  {
	    x = TREE_OPERAND (TREE_OPERAND (x, 0), 0);
	    break;
	  }
	if (TREE_CODE (TREE_OPERAND (x, 0)) == ADDR_EXPR)
	  {
	    x = TREE_OPERAND (x, 0);
	    break;
	  }
	return true;

      case VAR_DECL:
      case CONST_DECL:
      case PARM_DECL:
      case RESULT_DECL:
      case FUNCTION_DECL:
	TREE_ADDRESSABLE (x) = 1;
#if 0  /* poplevel deals with this now.  */
	if (DECL_CONTEXT (x) == 0)
	  TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
#endif
	/* drops through */
      default:
	return true;
    }
}
示例#3
0
void
cp_genericize (tree fndecl)
{
  tree t;
  struct pointer_set_t *p_set;

  /* Fix up the types of parms passed by invisible reference.  */
  for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
    if (TREE_ADDRESSABLE (TREE_TYPE (t)))
      {
	/* If a function's arguments are copied to create a thunk,
	   then DECL_BY_REFERENCE will be set -- but the type of the
	   argument will be a pointer type, so we will never get
	   here.  */
	gcc_assert (!DECL_BY_REFERENCE (t));
	gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
	TREE_TYPE (t) = DECL_ARG_TYPE (t);
	DECL_BY_REFERENCE (t) = 1;
	TREE_ADDRESSABLE (t) = 0;
	relayout_decl (t);
      }

  /* Do the same for the return value.  */
  if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
    {
      t = DECL_RESULT (fndecl);
      TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
      DECL_BY_REFERENCE (t) = 1;
      TREE_ADDRESSABLE (t) = 0;
      relayout_decl (t);
    }

  /* If we're a clone, the body is already GIMPLE.  */
  if (DECL_CLONED_FUNCTION_P (fndecl))
    return;

  /* We do want to see every occurrence of the parms, so we can't just use
     walk_tree's hash functionality.  */
  p_set = pointer_set_create ();
  cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL);
  pointer_set_destroy (p_set);

  /* Do everything else.  */
  c_genericize (fndecl);

  gcc_assert (bc_label[bc_break] == NULL);
  gcc_assert (bc_label[bc_continue] == NULL);
}
示例#4
0
文件: method.c 项目: asdlei00/freebsd
tree
make_alias_for (tree function, tree newid)
{
    tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
    DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
    cxx_dup_lang_specific_decl (alias);
    DECL_CONTEXT (alias) = NULL;
    TREE_READONLY (alias) = TREE_READONLY (function);
    TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
    TREE_PUBLIC (alias) = 0;
    DECL_INTERFACE_KNOWN (alias) = 1;
    DECL_NOT_REALLY_EXTERN (alias) = 1;
    DECL_THIS_STATIC (alias) = 1;
    DECL_SAVED_FUNCTION_DATA (alias) = NULL;
    DECL_DESTRUCTOR_P (alias) = 0;
    DECL_CONSTRUCTOR_P (alias) = 0;
    DECL_CLONED_FUNCTION (alias) = NULL_TREE;
    DECL_EXTERNAL (alias) = 0;
    DECL_ARTIFICIAL (alias) = 1;
    DECL_NO_STATIC_CHAIN (alias) = 1;
    DECL_PENDING_INLINE_P (alias) = 0;
    DECL_INLINE (alias) = 0;
    DECL_DECLARED_INLINE_P (alias) = 0;
    DECL_DEFERRED_FN (alias) = 0;
    DECL_USE_TEMPLATE (alias) = 0;
    DECL_TEMPLATE_INSTANTIATED (alias) = 0;
    DECL_TEMPLATE_INFO (alias) = NULL;
    DECL_INITIAL (alias) = error_mark_node;
    TREE_ADDRESSABLE (alias) = 1;
    TREE_USED (alias) = 1;
    SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
    return alias;
}
示例#5
0
static bool
suitable_for_tail_call_opt_p (void)
{
  tree param;

  /* alloca (until we have stack slot life analysis) inhibits
     sibling call optimizations, but not tail recursion.  */
  if (cfun->calls_alloca)
    return false;

  /* If we are using sjlj exceptions, we may need to add a call to
     _Unwind_SjLj_Unregister at exit of the function.  Which means
     that we cannot do any sibcall transformations.  */
  if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
      && current_function_has_exception_handlers ())
    return false;

  /* Any function that calls setjmp might have longjmp called from
     any called function.  ??? We really should represent this
     properly in the CFG so that this needn't be special cased.  */
  if (cfun->calls_setjmp)
    return false;

  /* ??? It is OK if the argument of a function is taken in some cases,
     but not in all cases.  See PR15387 and PR19616.  Revisit for 4.1.  */
  for (param = DECL_ARGUMENTS (current_function_decl);
       param;
       param = DECL_CHAIN (param))
    if (TREE_ADDRESSABLE (param))
      return false;

  return true;
}
示例#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);
}
示例#7
0
static tree
build_equiv_decl (tree union_type, bool is_init)
{
  tree decl;

  if (is_init)
    {
      decl = gfc_create_var (union_type, "equiv");
      TREE_STATIC (decl) = 1;
      return decl;
    }

  decl = build_decl (VAR_DECL, NULL, union_type);
  DECL_ARTIFICIAL (decl) = 1;

  DECL_COMMON (decl) = 1;

  TREE_ADDRESSABLE (decl) = 1;
  TREE_USED (decl) = 1;

  /* The source location has been lost, and doesn't really matter.
     We need to set it to something though.  */
  gfc_set_decl_location (decl, &gfc_current_locus);

  gfc_add_decl_to_function (decl);

  return decl;
}
示例#8
0
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)))
    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
    {
      if (DECL_P (t))
        TREE_ADDRESSABLE (t) = 1;
      t = build1 (ADDR_EXPR, natural_type, t);
    }

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

  return t;
}
示例#9
0
static tree
make_fname_decl ()
{
    const char *name = lang_hooks.decl_printable_name (current_function_decl, 0);
    tree decl, type, init;
    size_t length = strlen (name);

    type = build_array_type (build_type_variant (char_type_node, true, false),
                             build_index_type (size_int (length)));

    decl = build_decl (UNKNOWN_LOCATION, VAR_DECL,
                       get_identifier ("__function_name__"), type);

    TREE_STATIC (decl) = 1;
    TREE_READONLY (decl) = 1;
    DECL_ARTIFICIAL (decl) = 1;

    init = build_string (length + 1, name);
    TREE_TYPE (init) = type;
    TREE_READONLY (init) = 1;
    DECL_READ_P (decl) = 1;
    DECL_INITIAL (decl) = init;

    TREE_USED (decl) = 1;
    TREE_ADDRESSABLE (decl) = 1;
    DECL_CONTEXT (decl) = current_function_decl;

    return decl;
}
示例#10
0
static tree
build_equiv_decl (tree union_type, bool is_init)
{
  tree decl;
  char name[15];
  static int serial = 0;

  if (is_init)
    {
      decl = gfc_create_var (union_type, "equiv");
      TREE_STATIC (decl) = 1;
      return decl;
    }

  snprintf (name, sizeof (name), "equiv.%d", serial++);
  decl = build_decl (VAR_DECL, get_identifier (name), union_type);
  DECL_ARTIFICIAL (decl) = 1;
  DECL_IGNORED_P (decl) = 1;

  if (!gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl)))
    TREE_STATIC (decl) = 1;

  TREE_ADDRESSABLE (decl) = 1;
  TREE_USED (decl) = 1;

  /* The source location has been lost, and doesn't really matter.
     We need to set it to something though.  */
  gfc_set_decl_location (decl, &gfc_current_locus);

  gfc_add_decl_to_function (decl);

  return decl;
}
示例#11
0
static void
update_cloned_parm (tree parm, tree cloned_parm, bool first)
{
  DECL_ABSTRACT_ORIGIN (cloned_parm) = parm;

  /* We may have taken its address.  */
  TREE_ADDRESSABLE (cloned_parm) = TREE_ADDRESSABLE (parm);

  /* The definition might have different constness.  */
  TREE_READONLY (cloned_parm) = TREE_READONLY (parm);

  TREE_USED (cloned_parm) = !first || TREE_USED (parm);

  /* The name may have changed from the declaration.  */
  DECL_NAME (cloned_parm) = DECL_NAME (parm);
  DECL_SOURCE_LOCATION (cloned_parm) = DECL_SOURCE_LOCATION (parm);
  TREE_TYPE (cloned_parm) = TREE_TYPE (parm);
}
示例#12
0
tree
copy_var_decl (tree var, tree name, tree type)
{
  tree copy = build_decl (DECL_SOURCE_LOCATION (var), VAR_DECL, name, type);

  TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
  TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
  DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
  DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
  DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
  DECL_CONTEXT (copy) = DECL_CONTEXT (var);
  TREE_NO_WARNING (copy) = TREE_NO_WARNING (var);
  TREE_USED (copy) = 1;
  DECL_SEEN_IN_BIND_EXPR_P (copy) = 1;
  DECL_ATTRIBUTES (copy) = DECL_ATTRIBUTES (var);

  return copy;
}
示例#13
0
tree
gfc_build_array_ref (tree base, tree offset)
{
  tree type = TREE_TYPE (base);
  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
  type = TREE_TYPE (type);

  if (DECL_P (base))
    TREE_ADDRESSABLE (base) = 1;

  return build4 (ARRAY_REF, type, base, offset, NULL_TREE, NULL_TREE);
}
static void
mark_address_taken (tree ref)
{
  tree var;

  /* Note that it is *NOT OKAY* to use the target of a COMPONENT_REF
     as the only thing we take the address of.  If VAR is a structure,
     taking the address of a field means that the whole structure may
     be referenced using pointer arithmetic.  See PR 21407 and the
     ensuing mailing list discussion.  */
  var = get_base_address (ref);
  if (var)
    {
      if (DECL_P (var))
	TREE_ADDRESSABLE (var) = 1;
      else if (TREE_CODE (var) == MEM_REF
	       && TREE_CODE (TREE_OPERAND (var, 0)) == ADDR_EXPR
	       && DECL_P (TREE_OPERAND (TREE_OPERAND (var, 0), 0)))
	TREE_ADDRESSABLE (TREE_OPERAND (TREE_OPERAND (var, 0), 0)) = 1;
    }
}
示例#15
0
static void
mark_addressable_1 (tree x)
{
  if (!currently_expanding_to_rtl)
    {
      TREE_ADDRESSABLE (x) = 1;
      return;
    }

  if (!mark_addressable_queue)
    mark_addressable_queue = new hash_set<tree>();
  mark_addressable_queue->add (x);
}
示例#16
0
/* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is
   eligible for instrumentation.  For the mudflap1 pass, this implies
   that it should be registered with the libmudflap runtime.  For the
   mudflap2 pass this means instrumenting an indirection operation with
   respect to the object.
*/
static int
mf_decl_eligible_p (tree decl)
{
  return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
          /* The decl must have its address taken.  In the case of
             arrays, this flag is also set if the indexes are not
             compile-time known valid constants.  */
          && TREE_ADDRESSABLE (decl)    /* XXX: not sufficient: return-by-value structs! */
          /* The type of the variable must be complete.  */
          && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
	  /* The decl hasn't been decomposed somehow.  */
	  && !DECL_HAS_VALUE_EXPR_P (decl));
}
示例#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);
}
示例#18
0
文件: method.c 项目: Fokycnuk/gcc
static tree
make_alias_for_thunk (tree function)
{
  tree alias;
  char buf[256];

#if defined (TARGET_IS_PE_COFF)
  if (DECL_ONE_ONLY (function))
    return function;
#endif

  ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
  thunk_labelno++;
  alias = build_decl (FUNCTION_DECL, get_identifier (buf),
		      TREE_TYPE (function));
  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
  cxx_dup_lang_specific_decl (alias);
  DECL_CONTEXT (alias) = NULL;
  TREE_READONLY (alias) = TREE_READONLY (function);
  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
  TREE_PUBLIC (alias) = 0;
  DECL_INTERFACE_KNOWN (alias) = 1;
  DECL_NOT_REALLY_EXTERN (alias) = 1;
  DECL_THIS_STATIC (alias) = 1;
  DECL_SAVED_FUNCTION_DATA (alias) = NULL;
  DECL_DESTRUCTOR_P (alias) = 0;
  DECL_CONSTRUCTOR_P (alias) = 0;
  DECL_CLONED_FUNCTION (alias) = NULL_TREE;
  DECL_EXTERNAL (alias) = 0;
  DECL_ARTIFICIAL (alias) = 1;
  DECL_NO_STATIC_CHAIN (alias) = 1;
  DECL_PENDING_INLINE_P (alias) = 0;
  DECL_INLINE (alias) = 0;
  DECL_DECLARED_INLINE_P (alias) = 0;
  DECL_DEFERRED_FN (alias) = 0;
  DECL_USE_TEMPLATE (alias) = 0;
  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
  DECL_TEMPLATE_INFO (alias) = NULL;
  DECL_INITIAL (alias) = error_mark_node;
  TREE_ADDRESSABLE (alias) = 1;
  TREE_USED (alias) = 1;
  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
  if (!flag_syntax_only)
    assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
  return alias;
}
示例#19
0
文件: ubsan.c 项目: acoxepochlabs/gcc
tree
ubsan_encode_value (tree t, bool in_expand_p)
{
  tree type = TREE_TYPE (t);
  const unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
  if (bitsize <= POINTER_SIZE)
    switch (TREE_CODE (type))
      {
      case BOOLEAN_TYPE:
      case ENUMERAL_TYPE:
      case INTEGER_TYPE:
	return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
      case REAL_TYPE:
	{
	  tree itype = build_nonstandard_integer_type (bitsize, true);
	  t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
	  return fold_convert (pointer_sized_int_node, t);
	}
      default:
	gcc_unreachable ();
      }
  else
    {
      if (!DECL_P (t) || !TREE_ADDRESSABLE (t))
	{
	  /* The reason for this is that we don't want to pessimize
	     code by making vars unnecessarily addressable.  */
	  tree var = create_tmp_var (type, NULL);
	  tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
	  if (in_expand_p)
	    {
	      rtx mem
		= assign_stack_temp_for_type (TYPE_MODE (type),
					      GET_MODE_SIZE (TYPE_MODE (type)),
					      type);
	      SET_DECL_RTL (var, mem);
	      expand_assignment (var, t, false);
	      return build_fold_addr_expr (var);
	    }
	  t = build_fold_addr_expr (var);
	  return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
	}
      else
	return build_fold_addr_expr (t);
    }
}
示例#20
0
tree
create_tmp_var (tree type, const char *prefix)
{
  tree tmp_var;

  /* We don't allow types that are addressable (meaning we can't make copies),
     or incomplete.  We also used to reject every variable size objects here,
     but now support those for which a constant upper bound can be obtained.
     The processing for variable sizes is performed in gimple_add_tmp_var,
     point at which it really matters and possibly reached via paths not going
     through this function, e.g. after direct calls to create_tmp_var_raw.  */
  gcc_assert (!TREE_ADDRESSABLE (type) && COMPLETE_TYPE_P (type));

  tmp_var = create_tmp_var_raw (type, prefix);
  gimple_add_tmp_var (tmp_var);
  return tmp_var;
}
示例#21
0
static bool
slang_mark_addressable (tree exp)
{
  switch (TREE_CODE (exp)){
  case STRING_CST:
    break;
  case FUNCTION_DECL:
    TREE_ADDRESSABLE (exp) = 1;
    break;
  case ARRAY_REF:
    return slang_mark_addressable (TREE_OPERAND (exp, 0));
    break;
  default:
    gcc_unreachable();
    break;
  }
  return true;
}
示例#22
0
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;
}
示例#23
0
文件: trans.c 项目: PeyloW/gcc-4.6.4
tree
gfc_build_array_ref (tree base, tree offset, tree decl)
{
  tree type = TREE_TYPE (base);
  tree tmp;

  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
  type = TREE_TYPE (type);

  if (DECL_P (base))
    TREE_ADDRESSABLE (base) = 1;

  /* Strip NON_LVALUE_EXPR nodes.  */
  STRIP_TYPE_NOPS (offset);

  /* If the array reference is to a pointer, whose target contains a
     subreference, use the span that is stored with the backend decl
     and reference the element with pointer arithmetic.  */
  if (decl && (TREE_CODE (decl) == FIELD_DECL
		 || TREE_CODE (decl) == VAR_DECL
		 || TREE_CODE (decl) == PARM_DECL)
	&& GFC_DECL_SUBREF_ARRAY_P (decl)
	&& !integer_zerop (GFC_DECL_SPAN(decl)))
    {
      offset = fold_build2_loc (input_location, MULT_EXPR,
				gfc_array_index_type,
				offset, GFC_DECL_SPAN(decl));
      tmp = gfc_build_addr_expr (pvoid_type_node, base);
      tmp = fold_build2_loc (input_location, POINTER_PLUS_EXPR,
			     pvoid_type_node, tmp,
			     fold_convert (sizetype, offset));
      tmp = fold_convert (build_pointer_type (type), tmp);
      if (!TYPE_STRING_FLAG (type))
	tmp = build_fold_indirect_ref_loc (input_location, tmp);
      return tmp;
    }
  else
    /* Otherwise use a straightforward array reference.  */
    return build4_loc (input_location, ARRAY_REF, type, base, offset,
		       NULL_TREE, NULL_TREE);
}
示例#24
0
void
genrtl_scope_stmt (tree t)
{
    tree block = SCOPE_STMT_BLOCK (t);

    if (!SCOPE_NO_CLEANUPS_P (t))
    {
        if (SCOPE_BEGIN_P (t))
            expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t), block);
        else if (SCOPE_END_P (t))
            expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
    }
    else if (!SCOPE_NULLIFIED_P (t))
    {
        rtx note = emit_note (SCOPE_BEGIN_P (t)
                              ? NOTE_INSN_BLOCK_BEG : NOTE_INSN_BLOCK_END);
        NOTE_BLOCK (note) = block;
    }

    /* If we're at the end of a scope that contains inlined nested
       functions, we have to decide whether or not to write them out.  */
    if (block && SCOPE_END_P (t))
    {
        tree fn;

        for (fn = BLOCK_VARS (block); fn; fn = TREE_CHAIN (fn))
        {
            if (TREE_CODE (fn) == FUNCTION_DECL
                    && DECL_CONTEXT (fn) == current_function_decl
                    && DECL_SAVED_INSNS (fn)
                    && DECL_SAVED_INSNS (fn)->saved_for_inline
                    && !TREE_ASM_WRITTEN (fn)
                    && TREE_ADDRESSABLE (fn))
            {
                push_function_context ();
                output_inline_function (fn);
                pop_function_context ();
            }
        }
    }
}
示例#25
0
static void
lower_builtin_posix_memalign (gimple_stmt_iterator *gsi)
{
  gimple stmt, call = gsi_stmt (*gsi);
  tree pptr = gimple_call_arg (call, 0);
  tree align = gimple_call_arg (call, 1);
  tree res = gimple_call_lhs (call);
  tree ptr = create_tmp_reg (ptr_type_node, NULL);
  if (TREE_CODE (pptr) == ADDR_EXPR)
    {
      tree tem = create_tmp_var (ptr_type_node, NULL);
      TREE_ADDRESSABLE (tem) = 1;
      gimple_call_set_arg (call, 0, build_fold_addr_expr (tem));
      stmt = gimple_build_assign (ptr, tem);
    }
  else
    stmt = gimple_build_assign (ptr,
				fold_build2 (MEM_REF, ptr_type_node, pptr,
					     build_int_cst (ptr_type_node, 0)));
  if (res == NULL_TREE)
    {
      res = create_tmp_reg (integer_type_node, NULL);
      gimple_call_set_lhs (call, res);
    }
  tree align_label = create_artificial_label (UNKNOWN_LOCATION);
  tree noalign_label = create_artificial_label (UNKNOWN_LOCATION);
  gimple cond = gimple_build_cond (EQ_EXPR, res, integer_zero_node,
				   align_label, noalign_label);
  gsi_insert_after (gsi, cond, GSI_NEW_STMT);
  gsi_insert_after (gsi, gimple_build_label (align_label), GSI_NEW_STMT);
  gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
  stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_ASSUME_ALIGNED),
			    2, ptr, align);
  gimple_call_set_lhs (stmt, ptr);
  gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
  stmt = gimple_build_assign (fold_build2 (MEM_REF, ptr_type_node, pptr,
					   build_int_cst (ptr_type_node, 0)),
			      ptr);
  gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
  gsi_insert_after (gsi, gimple_build_label (noalign_label), GSI_NEW_STMT);
}
示例#26
0
tree
ubsan_encode_value (tree t)
{
  tree type = TREE_TYPE (t);
  switch (TREE_CODE (type))
    {
    case INTEGER_TYPE:
      if (TYPE_PRECISION (type) <= POINTER_SIZE)
	return fold_build1 (NOP_EXPR, pointer_sized_int_node, t);
      else
	return build_fold_addr_expr (t);
    case REAL_TYPE:
      {
	unsigned int bitsize = GET_MODE_BITSIZE (TYPE_MODE (type));
	if (bitsize <= POINTER_SIZE)
	  {
	    tree itype = build_nonstandard_integer_type (bitsize, true);
	    t = fold_build1 (VIEW_CONVERT_EXPR, itype, t);
	    return fold_convert (pointer_sized_int_node, t);
	  }
	else
	  {
	    if (!TREE_ADDRESSABLE (t))
	      {
		/* The reason for this is that we don't want to pessimize
		   code by making vars unnecessarily addressable.  */
		tree var = create_tmp_var (TREE_TYPE (t), NULL);
		tree tem = build2 (MODIFY_EXPR, void_type_node, var, t);
		t = build_fold_addr_expr (var);
		return build2 (COMPOUND_EXPR, TREE_TYPE (t), tem, t);
	      }
	    else
	      return build_fold_addr_expr (t);
	  }
      }
    default:
      gcc_unreachable ();
    }
}
示例#27
0
tree
make_alias_for (tree target, tree newid)
{
  tree alias = build_decl (DECL_SOURCE_LOCATION (target),
			   TREE_CODE (target), newid, TREE_TYPE (target));
  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (target);
  cxx_dup_lang_specific_decl (alias);
  DECL_CONTEXT (alias) = NULL;
  TREE_READONLY (alias) = TREE_READONLY (target);
  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (target);
  TREE_PUBLIC (alias) = 0;
  DECL_INTERFACE_KNOWN (alias) = 1;
  if (DECL_LANG_SPECIFIC (alias))
    {
      DECL_NOT_REALLY_EXTERN (alias) = 1;
      DECL_USE_TEMPLATE (alias) = 0;
      DECL_TEMPLATE_INFO (alias) = NULL;
    }
  DECL_EXTERNAL (alias) = 0;
  DECL_ARTIFICIAL (alias) = 1;
  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
  if (TREE_CODE (alias) == FUNCTION_DECL)
    {
      DECL_SAVED_FUNCTION_DATA (alias) = NULL;
      DECL_DESTRUCTOR_P (alias) = 0;
      DECL_CONSTRUCTOR_P (alias) = 0;
      DECL_PENDING_INLINE_P (alias) = 0;
      DECL_DECLARED_INLINE_P (alias) = 0;
      DECL_INITIAL (alias) = error_mark_node;
      DECL_ARGUMENTS (alias) = copy_list (DECL_ARGUMENTS (target));
    }
  else
    TREE_STATIC (alias) = 1;
  TREE_ADDRESSABLE (alias) = 1;
  TREE_USED (alias) = 1;
  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
  return alias;
}
示例#28
0
static void
create_vop_var (struct function *fn)
{
  tree global_var;

  gcc_assert (fn->gimple_df->vop == NULL_TREE);

  global_var = build_decl (BUILTINS_LOCATION, VAR_DECL,
			   get_identifier (".MEM"),
			   void_type_node);
  DECL_ARTIFICIAL (global_var) = 1;
  DECL_IGNORED_P (global_var) = 1;
  TREE_READONLY (global_var) = 0;
  DECL_EXTERNAL (global_var) = 1;
  TREE_STATIC (global_var) = 1;
  TREE_USED (global_var) = 1;
  DECL_CONTEXT (global_var) = NULL_TREE;
  TREE_THIS_VOLATILE (global_var) = 0;
  TREE_ADDRESSABLE (global_var) = 0;
  VAR_DECL_IS_VIRTUAL_OPERAND (global_var) = 1;

  fn->gimple_df->vop = global_var;
}
static void
create_vop_var (void)
{
  tree global_var;

  gcc_assert (cfun->gimple_df->vop == NULL_TREE);

  global_var = build_decl (BUILTINS_LOCATION, VAR_DECL,
			   get_identifier (".MEM"),
			   void_type_node);
  DECL_ARTIFICIAL (global_var) = 1;
  TREE_READONLY (global_var) = 0;
  DECL_EXTERNAL (global_var) = 1;
  TREE_STATIC (global_var) = 1;
  TREE_USED (global_var) = 1;
  DECL_CONTEXT (global_var) = NULL_TREE;
  TREE_THIS_VOLATILE (global_var) = 0;
  TREE_ADDRESSABLE (global_var) = 0;

  create_var_ann (global_var);
  add_referenced_var (global_var);
  cfun->gimple_df->vop = global_var;
}
示例#30
0
static void
create_common (gfc_common_head *com, segment_info *head, bool saw_equiv)
{
  segment_info *s, *next_s;
  tree union_type;
  tree *field_link;
  tree field;
  tree field_init = NULL_TREE;
  record_layout_info rli;
  tree decl;
  bool is_init = false;
  bool is_saved = false;

  /* Declare the variables inside the common block.
     If the current common block contains any equivalence object, then
     make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the
     alias analyzer work well when there is no address overlapping for
     common variables in the current common block.  */
  if (saw_equiv)
    union_type = make_node (UNION_TYPE);
  else
    union_type = make_node (RECORD_TYPE);

  rli = start_record_layout (union_type);
  field_link = &TYPE_FIELDS (union_type);

  /* Check for overlapping initializers and replace them with a single,
     artificial field that contains all the data.  */
  if (saw_equiv)
    field = get_init_field (head, union_type, &field_init, rli);
  else
    field = NULL_TREE;

  if (field != NULL_TREE)
    {
      is_init = true;
      *field_link = field;
      field_link = &DECL_CHAIN (field);
    }

  for (s = head; s; s = s->next)
    {
      build_field (s, union_type, rli);

      /* Link the field into the type.  */
      *field_link = s->field;
      field_link = &DECL_CHAIN (s->field);

      /* Has initial value.  */
      if (s->sym->value)
        is_init = true;

      /* Has SAVE attribute.  */
      if (s->sym->attr.save)
        is_saved = true;
    }

  finish_record_layout (rli, true);

  if (com)
    decl = build_common_decl (com, union_type, is_init);
  else
    decl = build_equiv_decl (union_type, is_init, is_saved);

  if (is_init)
    {
      tree ctor, tmp;
      VEC(constructor_elt,gc) *v = NULL;

      if (field != NULL_TREE && field_init != NULL_TREE)
	CONSTRUCTOR_APPEND_ELT (v, field, field_init);
      else
	for (s = head; s; s = s->next)
	  {
	    if (s->sym->value)
	      {
		/* Add the initializer for this field.  */
		tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts,
					    TREE_TYPE (s->field),
					    s->sym->attr.dimension,
					    s->sym->attr.pointer
					    || s->sym->attr.allocatable, false);

		CONSTRUCTOR_APPEND_ELT (v, s->field, tmp);
	      }
	  }

      gcc_assert (!VEC_empty (constructor_elt, v));
      ctor = build_constructor (union_type, v);
      TREE_CONSTANT (ctor) = 1;
      TREE_STATIC (ctor) = 1;
      DECL_INITIAL (decl) = ctor;

#ifdef ENABLE_CHECKING
      {
	tree field, value;
	unsigned HOST_WIDE_INT idx;
	FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value)
	  gcc_assert (TREE_CODE (field) == FIELD_DECL);
      }
#endif
    }

  /* Build component reference for each variable.  */
  for (s = head; s; s = next_s)
    {
      tree var_decl;

      var_decl = build_decl (s->sym->declared_at.lb->location,
			     VAR_DECL, DECL_NAME (s->field),
			     TREE_TYPE (s->field));
      TREE_STATIC (var_decl) = TREE_STATIC (decl);
      /* Mark the variable as used in order to avoid warnings about
	 unused variables.  */
      TREE_USED (var_decl) = 1;
      if (s->sym->attr.use_assoc)
	DECL_IGNORED_P (var_decl) = 1;
      if (s->sym->attr.target)
	TREE_ADDRESSABLE (var_decl) = 1;
      /* Fake variables are not visible from other translation units. */
      TREE_PUBLIC (var_decl) = 0;

      /* To preserve identifier names in COMMON, chain to procedure
         scope unless at top level in a module definition.  */
      if (com
          && s->sym->ns->proc_name
          && s->sym->ns->proc_name->attr.flavor == FL_MODULE)
	var_decl = pushdecl_top_level (var_decl);
      else
	gfc_add_decl_to_function (var_decl);

      SET_DECL_VALUE_EXPR (var_decl,
			   fold_build3_loc (input_location, COMPONENT_REF,
					    TREE_TYPE (s->field),
					    decl, s->field, NULL_TREE));
      DECL_HAS_VALUE_EXPR_P (var_decl) = 1;
      GFC_DECL_COMMON_OR_EQUIV (var_decl) = 1;

      if (s->sym->attr.assign)
	{
	  gfc_allocate_lang_decl (var_decl);
	  GFC_DECL_ASSIGN (var_decl) = 1;
	  GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field);
	  GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field);
	}

      s->sym->backend_decl = var_decl;

      next_s = s->next;
      free (s);
    }
}