f->x_stack_check_probe_note = NULL;
f->x_arg_pointer_save_area = NULL;
f->x_parm_birth_insn = NULL;
- f->original_arg_vector = NULL;
- f->original_decl_initial = NULL;
f->epilogue_delay_list = NULL;
}
\f
static struct temp_slot **
temp_slots_at_level (int level)
{
+ if (level >= (int) VEC_length (temp_slot_p, used_temp_slots))
+ {
+ size_t old_length = VEC_length (temp_slot_p, used_temp_slots);
+ temp_slot_p *p;
- if (!used_temp_slots)
- VARRAY_GENERIC_PTR_INIT (used_temp_slots, 3, "used_temp_slots");
-
- while (level >= (int) VARRAY_ACTIVE_SIZE (used_temp_slots))
- VARRAY_PUSH_GENERIC_PTR (used_temp_slots, NULL);
+ VEC_safe_grow (temp_slot_p, gc, used_temp_slots, level + 1);
+ p = VEC_address (temp_slot_p, used_temp_slots);
+ memset (&p[old_length], 0,
+ sizeof (temp_slot_p) * (level + 1 - old_length));
+ }
- return (struct temp_slot **) &VARRAY_GENERIC_PTR (used_temp_slots, level);
+ return &(VEC_address (temp_slot_p, used_temp_slots)[level]);
}
/* Returns the maximal temporary slot level. */
if (!used_temp_slots)
return -1;
- return VARRAY_ACTIVE_SIZE (used_temp_slots) - 1;
+ return VEC_length (temp_slot_p, used_temp_slots) - 1;
}
/* Moves temporary slot TEMP to LEVEL. */
if (mode == BLKmode || memory_required)
{
HOST_WIDE_INT size = int_size_in_bytes (type);
- tree size_tree;
rtx tmp;
/* Zero sized arrays are GNU C extension. Set size to 1 to avoid
size = 1;
/* Unfortunately, we don't yet know how to allocate variable-sized
- temporaries. However, sometimes we have a fixed upper limit on
- the size (which is stored in TYPE_ARRAY_MAX_SIZE) and can use that
- instead. This is the case for Chill variable-sized strings. */
- if (size == -1 && TREE_CODE (type) == ARRAY_TYPE
- && TYPE_ARRAY_MAX_SIZE (type) != NULL_TREE
- && host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
- size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
-
- /* If we still haven't been able to get a size, see if the language
- can compute a maximum size. */
- if (size == -1
- && (size_tree = lang_hooks.types.max_size (type)) != 0
- && host_integerp (size_tree, 1))
- size = tree_low_cst (size_tree, 1);
+ temporaries. However, sometimes we can find a fixed upper limit on
+ the size, so try that instead. */
+ else if (size == -1)
+ size = max_int_size_in_bytes (type);
/* The size of the temporary may be too large to fit into an integer. */
/* ??? Not sure this should happen except for user silliness, so limit
tree type = (TYPE_P (exp)) ? exp : TREE_TYPE (exp);
+ /* DECL node associated with FNTYPE when relevant, which we might need to
+ check for by-invisible-reference returns, typically for CALL_EXPR input
+ EXPressions. */
+ tree fndecl = NULL_TREE;
+
if (fntype)
switch (TREE_CODE (fntype))
{
case CALL_EXPR:
- fntype = get_callee_fndecl (fntype);
- fntype = fntype ? TREE_TYPE (fntype) : 0;
+ fndecl = get_callee_fndecl (fntype);
+ fntype = fndecl ? TREE_TYPE (fndecl) : 0;
break;
case FUNCTION_DECL:
- fntype = TREE_TYPE (fntype);
+ fndecl = fntype;
+ fntype = TREE_TYPE (fndecl);
break;
case FUNCTION_TYPE:
case METHOD_TYPE:
if (TREE_CODE (type) == VOID_TYPE)
return 0;
+
/* If the front end has decided that this needs to be passed by
reference, do so. */
if ((TREE_CODE (exp) == PARM_DECL || TREE_CODE (exp) == RESULT_DECL)
&& DECL_BY_REFERENCE (exp))
return 1;
+
+ /* If the EXPression is a CALL_EXPR, honor DECL_BY_REFERENCE set on the
+ called function RESULT_DECL, meaning the function returns in memory by
+ invisible reference. This check lets front-ends not set TREE_ADDRESSABLE
+ on the function type, which used to be the way to request such a return
+ mechanism but might now be causing troubles at gimplification time if
+ temporaries with the function type need to be created. */
+ if (TREE_CODE (exp) == CALL_EXPR && fndecl && DECL_RESULT (fndecl)
+ && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))
+ return 1;
+
if (targetm.calls.return_in_memory (type, fntype))
return 1;
/* Types that are TREE_ADDRESSABLE must be constructed in memory,
return 0;
}
-/* Insert a type into the used types hash table. */
-void
-used_types_insert (tree t, struct function *func)
+/* Insert a TYPE into the used types hash table of CFUN. */
+static void
+used_types_insert_helper (tree type, struct function *func)
{
- if (t != NULL && func != NULL)
+ if (type != NULL && func != NULL)
{
void **slot;
if (func->used_types_hash == NULL)
func->used_types_hash = htab_create_ggc (37, htab_hash_pointer,
- htab_eq_pointer, NULL);
- slot = htab_find_slot (func->used_types_hash, t, INSERT);
+ htab_eq_pointer, NULL);
+ slot = htab_find_slot (func->used_types_hash, type, INSERT);
if (*slot == NULL)
- *slot = t;
+ *slot = type;
}
}
+/* Given a type, insert it into the used hash table in cfun. */
+void
+used_types_insert (tree t)
+{
+ while (POINTER_TYPE_P (t) || TREE_CODE (t) == ARRAY_TYPE)
+ t = TREE_TYPE (t);
+ t = TYPE_MAIN_VARIANT (t);
+ if (debug_info_level > DINFO_LEVEL_NONE)
+ used_types_insert_helper (t, cfun);
+}
+
struct tree_opt_pass pass_leaf_regs =
{
NULL, /* name */