Makefile.in (c-decl.o): Depend on rtl.h and expr.h.

* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
	* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
	(REG_BASE_VALUE): Remove unneeded cast to unsigned.
	(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
	(find_base_decl): New function, from c_find_base_decl in c-common.c.
	(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
	(get_alias_set): Likewise.
	Major rework to do more things and allow language-specific code
	to just handle special-cases.
	(record_alias_subset): Args are HOST_WIDE_INT.
	(record_component_alias): Local vars are HOST_WIDE_INT.
	Don't handle COMPLEX_EXPR.
	(get_varargs_alias_set): Moved from builtins.c.
	(get_frame_alias_set): New function.
	* builtins.c (expand_builtin_return_address): Use frame alias set.
	(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
	for setjmp buffer.
	(get_memory_rtx): Rework to use set_mem_attributes.
	(get_varargs_alias_set): Deleted from here.
	* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
	(c_find_base_decl): Deleted from here.
	(c_get_alias_set): Remove many cases and rework to just handle
	C-specific cases.
	* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
	* c-decl.c (rtl.h, expr.h): Now included.
	(init_decl_processing): Call record_component_aliases on array types.
	(grokdeclarator): Likewise.
	Set TREE_ADDRESSABLE for all fields that are not bitfields.
	* c-typeck.c (common_type): Call record_component_aliases for array.
	* caller-save.c (setup_save_areas): Rework register loop for unsigned.
	Set all save areas to the frame alias set.
	* calls.c (initialie_argument_information): Call set_mem_attributes.
	(compute_argument_addresses, expand_call): Likewise.
	* explow.c (set_mem_attributes): New function.
	(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
	* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
	LEN and OFFSET now HOST_WIDE_INT.
	(clear_by_pieces): Similar changes.
	(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
	(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
	(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
	(clear_by_pieces_1): Likewise.
	(emit_push_insn): Call set_mem_attributes.
	(expand_expr, case INDIRECT_REF): Likewise.
	(expand_expr, case VAR_DECL): Call change_address.
	* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
	tree_low_cst.
	(get_varargs_alias_set, get_frame_alias_set): New decls.
	(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
	(new_alias_set, set_mem_attributes): Likewse.
	* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
	(assign_stack_temp_for_type): Likewise.
	Can split slot even if alias set since can copy.
	Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
	(assign_temp): Use host_integerp and tree_low_cst.
	(put_var_into_stack): Properly handle SAVE_EXPR.
	(put_addressof_into_stack): Likewise.
	(assign_parms): Call set_mem_attributes.
	Delete #if 0 code.
	(fix_lexical_address): Put reference to chain into frame alias set.
	(expand_function_start): Call set_mem_attributes.
	* integrate.c (expand_inline_function): Likewise.
	* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
	* regmove.c (try_apply_stack_adjustment): Likewise.
	* reload.c (push_reload, make_memloc): Likewise.
	* reload1.c (alter_reg): Make alias sets for spilled pseudos.
	* rtl.def (MEM): Update comment.
	* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
	(move_by_pieces): Change length to HOST_WIDE_INT.
	(record_base_value, record_alias_subset): Delete from here.
	* stmt.c (expand_decl): Call set_mem_attributes.
	* stor-layout.c (finish_record_layout): Call record_component_aliases.i
	* toplev.c (compile_file): Call init_alias_once earlier.
	* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
	from here: now in alias.c.
	* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
	(struct tree_decl): Likewise.
	(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
	* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
	(output_constant_def, force_const_mem): Likewise.
	* cp/Makefile.in (decl.o): Include ../expr.h.
	* cp/decl.c (expr.h): Include.
	(init_decl_processing): Call record_component_aliases for arrays.
	(grokdeclarator): Likewise.
	Set TREE_ADDRESSABLE for fields that aren't bitfields.
	* cp/tree.c (build_cplus_array_type_1): Call record_component_aliases.

From-SVN: r34305
This commit is contained in:
Richard Kenner 2000-05-31 18:37:31 +00:00 committed by Richard Kenner
parent 99923eedd0
commit 3bdf5ad138
28 changed files with 736 additions and 574 deletions

View File

@ -32,6 +32,87 @@ Wed May 31 13:17:20 2000 Philippe De Muyter <phdm@macqel.be>
Wed May 31 08:07:52 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (c-decl.o): Depend on rtl.h and expr.h.
* alias.c (struct alias_entry): alias_set is HOST_WIDE_INT.
(REG_BASE_VALUE): Remove unneeded cast to unsigned.
(get_alias_set_entry): ALIAS_SET arg is HOST_WIDE_INT.
(find_base_decl): New function, from c_find_base_decl in c-common.c.
(new_alias_set): Moved from tree.c; return is HOST_WIDE_INT.
(get_alias_set): Likewise.
Major rework to do more things and allow language-specific code
to just handle special-cases.
(record_alias_subset): Args are HOST_WIDE_INT.
(record_component_alias): Local vars are HOST_WIDE_INT.
Don't handle COMPLEX_EXPR.
(get_varargs_alias_set): Moved from builtins.c.
(get_frame_alias_set): New function.
* builtins.c (expand_builtin_return_address): Use frame alias set.
(expand_builtin_setjmp, expand_builtin_longjmp): Use alias set
for setjmp buffer.
(get_memory_rtx): Rework to use set_mem_attributes.
(get_varargs_alias_set): Deleted from here.
* c-common.c (c_apply_type_quals_to_decl): Alias sets now HOST_WIDE_INT.
(c_find_base_decl): Deleted from here.
(c_get_alias_set): Remove many cases and rework to just handle
C-specific cases.
* c-common.h (c_get_alias_set): Returns HOST_WIDE_INT.
* c-decl.c (rtl.h, expr.h): Now included.
(init_decl_processing): Call record_component_aliases on array types.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for all fields that are not bitfields.
* c-typeck.c (common_type): Call record_component_aliases for array.
* caller-save.c (setup_save_areas): Rework register loop for unsigned.
Set all save areas to the frame alias set.
* calls.c (initialie_argument_information): Call set_mem_attributes.
(compute_argument_addresses, expand_call): Likewise.
* explow.c (set_mem_attributes): New function.
(stabilize): Use MEM_COPY_ATTRIBUTES and force_reg.
* expr.c (struct move_by_pieces): Remove {to,from}_{struct,readonly}.
LEN and OFFSET now HOST_WIDE_INT.
(clear_by_pieces): Similar changes.
(move_by_pieces): LEN now HOST_WIDE_INT; don't set deleted fields.
(move_by_pieces_ninsns): Now returns unsigned HOST_WIDE_INT.
(move_by_pieces_1): Don't use deleted fields, use MEM_COPY_ATTRIBUTES.
(clear_by_pieces_1): Likewise.
(emit_push_insn): Call set_mem_attributes.
(expand_expr, case INDIRECT_REF): Likewise.
(expand_expr, case VAR_DECL): Call change_address.
* expr.h (ADD_PARM_SIZE, SUB_PARM_SIZE): Use host_integerp and
tree_low_cst.
(get_varargs_alias_set, get_frame_alias_set): New decls.
(record_base_value, record_alias_subset, lang_get_alias_set): Likewise.
(new_alias_set, set_mem_attributes): Likewse.
* function.c (struct temp_slot): ALIAS_SET is HOST_WIDE_INT.
(assign_stack_temp_for_type): Likewise.
Can split slot even if alias set since can copy.
Set MEM_ALIAS_SET and MEM_SET_IN_STRUCT_P.
(assign_temp): Use host_integerp and tree_low_cst.
(put_var_into_stack): Properly handle SAVE_EXPR.
(put_addressof_into_stack): Likewise.
(assign_parms): Call set_mem_attributes.
Delete #if 0 code.
(fix_lexical_address): Put reference to chain into frame alias set.
(expand_function_start): Call set_mem_attributes.
* integrate.c (expand_inline_function): Likewise.
* recog.c (adj_offsettable_operand): Use MEM_COPY_ATTRIBUTES.
* regmove.c (try_apply_stack_adjustment): Likewise.
* reload.c (push_reload, make_memloc): Likewise.
* reload1.c (alter_reg): Make alias sets for spilled pseudos.
* rtl.def (MEM): Update comment.
* rtl.h (MEM_ALIAS_SET): Now uses XCWINT.
(move_by_pieces): Change length to HOST_WIDE_INT.
(record_base_value, record_alias_subset): Delete from here.
* stmt.c (expand_decl): Call set_mem_attributes.
* stor-layout.c (finish_record_layout): Call record_component_aliases.i
* toplev.c (compile_file): Call init_alias_once earlier.
* tree.c (lang_get_alias_set, get_alias_set, new_alias_set): Deleted
from here: now in alias.c.
* tree.h (struct tree_type): alias_set is HOST_WIDE_INT.
(struct tree_decl): Likewise.
(get_alias_set, new_alias_set, lang_get_alias_set): Deleted from here.
* varasm.c (make_function_rtl, make_decl_rtl): Call set_mem_attributes.
(output_constant_def, force_const_mem): Likewise.
* flow.c (propagate_block): If block has no successors, stores to
frame are dead if not used.

View File

@ -1092,12 +1092,13 @@ $(srcdir)/c-gperf.h: c-parse.gperf
exit 1 )
$(SHELL) $(srcdir)/move-if-change tmp-gperf.h $(srcdir)/c-gperf.h
c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h $(GGC_H) \
c-lex.h flags.h function.h output.h toplev.h defaults.h
c-decl.o : c-decl.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-tree.h \
c-common.h $(GGC_H) c-lex.h flags.h function.h output.h expr.h toplev.h \
defaults.h
c-typeck.o : c-typeck.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h
c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h $(GGC_H) \
c-lex.h toplev.h output.h function.h
c-lang.o : c-lang.c $(CONFIG_H) system.h $(TREE_H) c-tree.h c-common.h \
$(GGC_H) c-lex.h toplev.h output.h function.h
c-lex.o : c-lex.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) c-lex.h c-tree.h \
c-common.h $(srcdir)/c-parse.h $(srcdir)/c-gperf.h c-pragma.h input.h \
intl.h flags.h toplev.h output.h mbchar.h $(GGC_H)

View File

@ -57,10 +57,10 @@ Boston, MA 02111-1307, USA. */
In this situation we say the alias set for `struct S' is the
`superset' and that those for `int' and `double' are `subsets'.
To see whether two alias sets can point to the same memory, we must go
down the list of decendents of each and see if there is some alias set
in common. We need not trace past immediate decendents, however, since
we propagate all grandchildren up one level.
To see whether two alias sets can point to the same memory, we must
see if either alias set is a subset of the other. We need not trace
past immediate decendents, however, since we propagate all
grandchildren up one level.
Alias set zero is implicitly a superset of all other alias sets.
However, this is no actual entry for alias set zero. It is an
@ -69,7 +69,7 @@ Boston, MA 02111-1307, USA. */
typedef struct alias_set_entry
{
/* The alias set number, as stored in MEM_ALIAS_SET. */
int alias_set;
HOST_WIDE_INT alias_set;
/* The children of the alias set. These are not just the immediate
children, but, in fact, all decendents. So, if we have:
@ -81,6 +81,10 @@ typedef struct alias_set_entry
splay_tree children;
} *alias_set_entry;
/* The language-specific function for alias analysis. If NULL, the
language does not do any special alias analysis. */
HOST_WIDE_INT (*lang_get_alias_set) PARAMS ((tree));
static int rtx_equal_for_memref_p PARAMS ((rtx, rtx));
static rtx find_symbolic_term PARAMS ((rtx));
static rtx get_addr PARAMS ((rtx));
@ -93,9 +97,10 @@ static int base_alias_check PARAMS ((rtx, rtx, enum machine_mode,
static rtx find_base_value PARAMS ((rtx));
static int mems_in_disjoint_alias_sets_p PARAMS ((rtx, rtx));
static int insert_subset_children PARAMS ((splay_tree_node, void*));
static alias_set_entry get_alias_set_entry PARAMS ((int));
static tree find_base_decl PARAMS ((tree));
static alias_set_entry get_alias_set_entry PARAMS ((HOST_WIDE_INT));
static rtx fixed_scalar_and_varying_struct_p PARAMS ((rtx, rtx, rtx, rtx,
int (*)(rtx)));
int (*) (rtx)));
static int aliases_everything_p PARAMS ((rtx));
static int write_dependence_p PARAMS ((rtx, rtx, int));
static int nonlocal_reference_p PARAMS ((rtx));
@ -140,7 +145,7 @@ static rtx *new_reg_base_value;
static unsigned int reg_base_value_size; /* size of reg_base_value array */
#define REG_BASE_VALUE(X) \
((unsigned) REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
(REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
/* Vector of known invariant relationships between registers. Set in
loop unrolling. Indexed by register number, if nonzero the value
@ -187,7 +192,7 @@ static splay_tree alias_sets;
static alias_set_entry
get_alias_set_entry (alias_set)
int alias_set;
HOST_WIDE_INT alias_set;
{
splay_tree_node sn
= splay_tree_lookup (alias_sets, (splay_tree_key) alias_set);
@ -236,8 +241,7 @@ mems_in_disjoint_alias_sets_p (mem1, mem2)
if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2))
return 0;
/* Iterate through each of the children of the first alias set,
comparing it with the second alias set. */
/* See if the first alias set is a subset of the second. */
ase = get_alias_set_entry (MEM_ALIAS_SET (mem1));
if (ase != 0 && splay_tree_lookup (ase->children,
(splay_tree_key) MEM_ALIAS_SET (mem2)))
@ -266,6 +270,168 @@ insert_subset_children (node, data)
return 0;
}
/* T is an expression with pointer type. Find the DECL on which this
expression is based. (For example, in `a[i]' this would be `a'.)
If there is no such DECL, or a unique decl cannot be determined,
NULL_TREE is retured. */
static tree
find_base_decl (t)
tree t;
{
tree d0, d1, d2;
if (t == 0 || t == error_mark_node || ! POINTER_TYPE_P (TREE_TYPE (t)))
return 0;
/* If this is a declaration, return it. */
if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd')
return t;
/* Handle general expressions. It would be nice to deal with
COMPONENT_REFs here. If we could tell that `a' and `b' were the
same, then `a->f' and `b->f' are also the same. */
switch (TREE_CODE_CLASS (TREE_CODE (t)))
{
case '1':
return find_base_decl (TREE_OPERAND (t, 0));
case '2':
/* Return 0 if found in neither or both are the same. */
d0 = find_base_decl (TREE_OPERAND (t, 0));
d1 = find_base_decl (TREE_OPERAND (t, 1));
if (d0 == d1)
return d0;
else if (d0 == 0)
return d1;
else if (d1 == 0)
return d0;
else
return 0;
case '3':
d0 = find_base_decl (TREE_OPERAND (t, 0));
d1 = find_base_decl (TREE_OPERAND (t, 1));
d0 = find_base_decl (TREE_OPERAND (t, 0));
d2 = find_base_decl (TREE_OPERAND (t, 2));
/* Set any nonzero values from the last, then from the first. */
if (d1 == 0) d1 = d2;
if (d0 == 0) d0 = d1;
if (d1 == 0) d1 = d0;
if (d2 == 0) d2 = d1;
/* At this point all are nonzero or all are zero. If all three are the
same, return it. Otherwise, return zero. */
return (d0 == d1 && d1 == d2) ? d0 : 0;
default:
return 0;
}
}
/* Return the alias set for T, which may be either a type or an
expression. Call language-specific routine for help, if needed. */
HOST_WIDE_INT
get_alias_set (t)
tree t;
{
HOST_WIDE_INT set;
HOST_WIDE_INT bitsize, bitpos;
tree offset;
enum machine_mode mode;
int volatilep, unsignedp;
unsigned int alignment;
/* If we're not doing any alias analysis, just assume everything
aliases everything else. Also return 0 if this or its type is
an error. */
if (! flag_strict_aliasing || t == error_mark_node
|| (! TYPE_P (t)
&& (TREE_TYPE (t) == 0 || TREE_TYPE (t) == error_mark_node)))
return 0;
/* We can be passed either an expression or a type. This and the
language-specific routine may make mutually-recursive calls to
each other to figure out what to do. At each juncture, we see if
this is a tree that the language may need to handle specially.
But first remove nops since we care only about the actual object. */
while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
|| TREE_CODE (t) == NON_LVALUE_EXPR)
t = TREE_OPERAND (t, 0);
/* Now give the language a chance to do something. */
if (lang_get_alias_set != 0
&& (set = (*lang_get_alias_set) (t)) != -1)
return set;
/* If this is a reference, go inside it and use the underlying object. */
if (TREE_CODE_CLASS (TREE_CODE (t)) == 'r')
t = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode,
&unsignedp, &volatilep, &alignment);
if (TREE_CODE (t) == INDIRECT_REF)
{
/* Check for accesses through restrict-qualified pointers. */
tree decl = find_base_decl (TREE_OPERAND (t, 0));
if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
/* We use the alias set indicated in the declaration. */
return DECL_POINTER_ALIAS_SET (decl);
/* If we have an INDIRECT_REF via a void pointer, we don't know anything
about what that might alias. */
if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE)
return 0;
}
/* Give the language another chance to do something special. */
if (lang_get_alias_set != 0
&& (set = (*lang_get_alias_set) (t)) != -1)
return set;
/* Now we are done with expressions, so get the type if this isn't
a type. */
if (! TYPE_P (t))
t = TREE_TYPE (t);
/* Variant qualifiers don't affect the alias set, so get the main
variant. If this is a type with a known alias set, return it. */
t = TYPE_MAIN_VARIANT (t);
if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t))
return TYPE_ALIAS_SET (t);
/* See if the language has special handling for this type. */
if (lang_get_alias_set != 0
&& (set = (*lang_get_alias_set) (t)) != -1)
;
/* There are no objects of FUNCTION_TYPE, so there's no point in
using up an alias set for them. (There are, of course, pointers
and references to functions, but that's different.) */
else if (TREE_CODE (t) == FUNCTION_TYPE)
set = 0;
else
/* Otherwise make a new alias set for this type. */
set = new_alias_set ();
TYPE_ALIAS_SET (t) = set;
return set;
}
/* Return a brand-new alias set. */
HOST_WIDE_INT
new_alias_set ()
{
static HOST_WIDE_INT last_alias_set;
if (flag_strict_aliasing)
return ++last_alias_set;
else
return 0;
}
/* Indicate that things in SUBSET can alias things in SUPERSET, but
not vice versa. For example, in C, a store to an `int' can alias a
@ -278,8 +444,8 @@ insert_subset_children (node, data)
void
record_alias_subset (superset, subset)
int superset;
int subset;
HOST_WIDE_INT superset;
HOST_WIDE_INT subset;
{
alias_set_entry superset_entry;
alias_set_entry subset_entry;
@ -326,8 +492,8 @@ void
record_component_aliases (type)
tree type;
{
int superset = get_alias_set (type);
int subset;
HOST_WIDE_INT superset = get_alias_set (type);
HOST_WIDE_INT subset;
tree field;
if (superset == 0)
@ -336,7 +502,6 @@ record_component_aliases (type)
switch (TREE_CODE (type))
{
case ARRAY_TYPE:
case COMPLEX_TYPE:
subset = get_alias_set (TREE_TYPE (type));
if (subset != 0)
record_alias_subset (superset, subset);
@ -358,6 +523,34 @@ record_component_aliases (type)
}
}
/* Allocate an alias set for use in storing and reading from the varargs
spill area. */
HOST_WIDE_INT
get_varargs_alias_set ()
{
static HOST_WIDE_INT set = -1;
if (set == -1)
set = new_alias_set ();
return set;
}
/* Likewise, but used for the fixed portions of the frame, e.g., register
save areas. */
HOST_WIDE_INT
get_frame_alias_set ()
{
static HOST_WIDE_INT set = -1;
if (set == -1)
set = new_alias_set ();
return set;
}
/* Inside SRC, the source of a SET, find a base address. */
static rtx
@ -975,6 +1168,7 @@ base_alias_check (x, y, x_mode, y_mode)
/* Convert the address X into something we can use. This is done by returning
it unchanged unless it is a value; in the latter case we call cselib to get
a more useful rtx. */
static rtx
get_addr (x)
rtx x;

View File

@ -288,6 +288,7 @@ expand_builtin_return_addr (fndecl_code, count, tem)
#endif
tem = memory_address (Pmode, tem);
tem = copy_to_reg (gen_rtx_MEM (Pmode, tem));
MEM_ALIAS_SET (tem) = get_frame_alias_set ();
}
/* For __builtin_frame_address, return what we've got. */
@ -302,10 +303,14 @@ expand_builtin_return_addr (fndecl_code, count, tem)
tem = memory_address (Pmode,
plus_constant (tem, GET_MODE_SIZE (Pmode)));
tem = gen_rtx_MEM (Pmode, tem);
MEM_ALIAS_SET (tem) = get_frame_alias_set ();
#endif
return tem;
}
/* Alias set used for setjmp buffer. */
static HOST_WIDE_INT setjmp_alias_set = -1;
/* __builtin_setjmp is passed a pointer to an array of five words (not
all will be used on all machines). It operates similarly to the C
library function of the same name, but is more efficient. Much of
@ -326,9 +331,13 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
enum machine_mode value_mode;
rtx stack_save;
rtx mem;
value_mode = TYPE_MODE (integer_type_node);
if (setjmp_alias_set == -1)
setjmp_alias_set = new_alias_set ();
#ifdef POINTERS_EXTEND_UNSIGNED
buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
@ -349,17 +358,20 @@ expand_builtin_setjmp (buf_addr, target, first_label, next_label)
#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx
#endif
emit_move_insn (gen_rtx_MEM (Pmode, buf_addr),
BUILTIN_SETJMP_FRAME_VALUE);
emit_move_insn (validize_mem
(gen_rtx_MEM (Pmode,
plus_constant (buf_addr,
GET_MODE_SIZE (Pmode)))),
mem = gen_rtx_MEM (Pmode, buf_addr);
MEM_ALIAS_SET (mem) = setjmp_alias_set;
emit_move_insn (mem, BUILTIN_SETJMP_FRAME_VALUE);
mem = gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode))),
MEM_ALIAS_SET (mem) = setjmp_alias_set;
emit_move_insn (validize_mem (mem),
force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1)));
stack_save = gen_rtx_MEM (sa_mode,
plus_constant (buf_addr,
2 * GET_MODE_SIZE (Pmode)));
MEM_ALIAS_SET (stack_save) = setjmp_alias_set;
emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX);
/* If there is further processing to do, do it. */
@ -464,6 +476,9 @@ expand_builtin_longjmp (buf_addr, value)
rtx fp, lab, stack;
enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL);
if (setjmp_alias_set == -1)
setjmp_alias_set = new_alias_set ();
#ifdef POINTERS_EXTEND_UNSIGNED
buf_addr = convert_memory_address (Pmode, buf_addr);
#endif
@ -489,6 +504,8 @@ expand_builtin_longjmp (buf_addr, value)
stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr,
2 * GET_MODE_SIZE (Pmode)));
MEM_ALIAS_SET (fp) = MEM_ALIAS_SET (lab) = MEM_ALIAS_SET (stack)
= setjmp_alias_set;
/* Pick up FP, label, and SP from the block and jump. This code is
from expand_goto in stmt.c; see there for detailed comments. */
@ -513,53 +530,34 @@ expand_builtin_longjmp (buf_addr, value)
}
}
/* Get a MEM rtx for expression EXP which can be used in a string instruction
(cmpstrsi, movstrsi, ..). */
/* Get a MEM rtx for expression EXP which is the address of an operand
to be used to be used in a string instruction (cmpstrsi, movstrsi, ..). */
static rtx
get_memory_rtx (exp)
tree exp;
{
rtx mem;
int is_aggregate;
rtx mem = gen_rtx_MEM (BLKmode,
memory_address (BLKmode,
expand_expr (exp, NULL_RTX,
ptr_mode, EXPAND_SUM)));
mem = gen_rtx_MEM (BLKmode,
memory_address (BLKmode,
expand_expr (exp, NULL_RTX,
ptr_mode, EXPAND_SUM)));
/* Get an expression we can use to find the attributes to assign to MEM.
If it is an ADDR_EXPR, use the operand. Otherwise, dereference it if
we can. First remove any nops. */
while ((TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
|| TREE_CODE (exp) == NON_LVALUE_EXPR)
&& POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (exp, 0))))
exp = TREE_OPERAND (exp, 0);
RTX_UNCHANGING_P (mem) = TREE_READONLY (exp);
if (TREE_CODE (exp) == ADDR_EXPR)
exp = TREE_OPERAND (exp, 0);
else if (POINTER_TYPE_P (TREE_TYPE (exp)))
exp = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp);
else
return mem;
/* Figure out the type of the object pointed to. Set MEM_IN_STRUCT_P
if the value is the address of a structure or if the expression is
cast to a pointer to structure type. */
is_aggregate = 0;
while (TREE_CODE (exp) == NOP_EXPR)
{
tree cast_type = TREE_TYPE (exp);
if (TREE_CODE (cast_type) == POINTER_TYPE
&& AGGREGATE_TYPE_P (TREE_TYPE (cast_type)))
{
is_aggregate = 1;
break;
}
exp = TREE_OPERAND (exp, 0);
}
if (is_aggregate == 0)
{
tree type;
if (TREE_CODE (exp) == ADDR_EXPR)
/* If this is the address of an object, check whether the
object is an array. */
type = TREE_TYPE (TREE_OPERAND (exp, 0));
else
type = TREE_TYPE (TREE_TYPE (exp));
is_aggregate = AGGREGATE_TYPE_P (type);
}
MEM_SET_IN_STRUCT_P (mem, is_aggregate);
set_mem_attributes (mem, exp, 0);
return mem;
}
@ -1306,6 +1304,7 @@ expand_builtin_mathfn (exp, target, subtarget)
if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient (and in mode MODE if that's
convenient). */
static rtx
expand_builtin_strlen (exp, target, mode)
tree exp;
@ -1377,8 +1376,9 @@ expand_builtin_strlen (exp, target, mode)
TYPE_MODE (integer_type_node));
char_rtx = const0_rtx;
char_mode = insn_data[(int)icode].operand[2].mode;
if (! (*insn_data[(int)icode].operand[2].predicate) (char_rtx, char_mode))
char_mode = insn_data[(int) icode].operand[2].mode;
if (! (*insn_data[(int) icode].operand[2].predicate) (char_rtx,
char_mode))
char_rtx = copy_to_mode_reg (char_mode, char_rtx);
pat = GEN_FCN (icode) (result, gen_rtx_MEM (BLKmode, src_reg),
@ -1390,7 +1390,7 @@ expand_builtin_strlen (exp, target, mode)
/* Now that we are assured of success, expand the source. */
start_sequence ();
pat = memory_address (BLKmode,
expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
expand_expr (src, src_reg, ptr_mode, EXPAND_SUM));
if (pat != src_reg)
emit_move_insn (src_reg, pat);
pat = gen_sequence ();
@ -1814,6 +1814,7 @@ expand_builtin_saveregs ()
/* __builtin_args_info (N) returns word N of the arg space info
for the current function. The number and meanings of words
is controlled by the definition of CUMULATIVE_ARGS. */
static rtx
expand_builtin_args_info (exp)
tree exp;
@ -2007,19 +2008,9 @@ expand_builtin_va_start (stdarg_p, arglist)
return const0_rtx;
}
/* Allocate an alias set for use in storing and reading from the varargs
spill area. */
int
get_varargs_alias_set ()
{
static int set = -1;
if (set == -1)
set = new_alias_set ();
return set;
}
/* The "standard" implementation of va_arg: read the value from the
current (padded) address and increment by the (padded) size. */
rtx
std_expand_builtin_va_arg (valist, type)
tree valist, type;
@ -2063,6 +2054,7 @@ std_expand_builtin_va_arg (valist, type)
/* Expand __builtin_va_arg, which is not really a builtin function, but
a very special sort of operator. */
rtx
expand_builtin_va_arg (valist, type)
tree valist, type;
@ -2146,6 +2138,7 @@ expand_builtin_va_arg (valist, type)
}
/* Expand ARGLIST, from a call to __builtin_va_end. */
static rtx
expand_builtin_va_end (arglist)
tree arglist;
@ -2168,6 +2161,7 @@ expand_builtin_va_end (arglist)
/* Expand ARGLIST, from a call to __builtin_va_copy. We do this as a
builtin rather than just as an assignment in stdarg.h because of the
nastiness of array-type va_list types. */
static rtx
expand_builtin_va_copy (arglist)
tree arglist;

View File

@ -156,7 +156,6 @@ static void init_attributes PARAMS ((void));
static void record_function_format PARAMS ((tree, tree, enum format_type,
int, int));
static void record_international_format PARAMS ((tree, tree, int));
static tree c_find_base_decl PARAMS ((tree));
static int default_valid_lang_attribute PARAMS ((tree, tree, tree, tree));
/* Keep a stack of if statements. We record the number of compound
@ -3245,10 +3244,10 @@ c_apply_type_quals_to_decl (type_quals, decl)
alias set for the type pointed to by the type of the
decl. */
int pointed_to_alias_set
HOST_WIDE_INT pointed_to_alias_set
= get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
if (!pointed_to_alias_set)
if (pointed_to_alias_set == 0)
/* It's not legal to make a subset of alias set zero. */
;
else
@ -3261,91 +3260,16 @@ c_apply_type_quals_to_decl (type_quals, decl)
}
}
/* T is an expression with pointer type. Find the DECL on which this
expression is based. (For example, in `a[i]' this would be `a'.)
If there is no such DECL, or a unique decl cannot be determined,
NULL_TREE is retured. */
static tree
c_find_base_decl (t)
tree t;
{
int i;
tree decl;
if (t == NULL_TREE || t == error_mark_node)
return NULL_TREE;
if (!POINTER_TYPE_P (TREE_TYPE (t)))
return NULL_TREE;
decl = NULL_TREE;
if (TREE_CODE (t) == FIELD_DECL
|| TREE_CODE (t) == PARM_DECL
|| TREE_CODE (t) == VAR_DECL)
/* Aha, we found a pointer-typed declaration. */
return t;
/* It would be nice to deal with COMPONENT_REFs here. If we could
tell that `a' and `b' were the same, then `a->f' and `b->f' are
also the same. */
/* Handle general expressions. */
switch (TREE_CODE_CLASS (TREE_CODE (t)))
{
case '1':
case '2':
case '3':
for (i = TREE_CODE_LENGTH (TREE_CODE (t)); --i >= 0;)
{
tree d = c_find_base_decl (TREE_OPERAND (t, i));
if (d)
{
if (!decl)
decl = d;
else if (d && d != decl)
/* Two different declarations. That's confusing; let's
just assume we don't know what's going on. */
decl = NULL_TREE;
}
}
break;
default:
break;
}
return decl;
}
/* Return the typed-based alias set for T, which may be an expression
or a type. */
or a type. Return -1 if we don't do anything special. */
int
HOST_WIDE_INT
c_get_alias_set (t)
tree t;
{
tree type;
tree u;
if (t == error_mark_node)
return 0;
/* For a bit field reference that's not to a specific field,
all we can say is the aliasing information for the underlying object. */
if (TREE_CODE (t) == BIT_FIELD_REF)
t = TREE_OPERAND (t, 0);
/* If this is a type, use it, otherwise get the type of the expression.
If the type is an error type, say this may alias anything. */
type = TYPE_P (t) ? t : TREE_TYPE (t);
if (type == error_mark_node)
return 0;
/* Deal with special cases first; for certain kinds of references
we're interested in more than just the type. */
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
permit taking the address of a union member and then storing
@ -3359,81 +3283,37 @@ c_get_alias_set (t)
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
return 0;
if (TREE_CODE (t) == INDIRECT_REF)
/* If this is a char *, the ANSI C standard says it can alias
anything. */
else if (TREE_CODE (t) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (t, 0)))
== TYPE_PRECISION (char_type_node)))
return 0;
/* That's all the expressions we handle specially. */
if (! TYPE_P (t))
return -1;
if (TREE_CODE (t) == INTEGER_TYPE)
{
/* Check for accesses through restrict-qualified pointers. */
tree op = TREE_OPERAND (t, 0);
tree decl = c_find_base_decl (op);
if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
/* We use the alias set indicated in the declaration. */
return DECL_POINTER_ALIAS_SET (decl);
/* If this is a char *, the ANSI C standard says it can alias
anything. */
if (TREE_CODE (TREE_TYPE (op)) == INTEGER_TYPE
&& (TYPE_PRECISION (TREE_TYPE (op))
== TYPE_PRECISION (char_type_node)))
return 0;
}
/* From here on, only the type matters. */
if (TREE_CODE (t) == COMPONENT_REF
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)))
/* Since build_modify_expr calls get_unwidened for stores to
component references, the type of a bit field can be changed
from (say) `unsigned int : 16' to `unsigned short' or from
`enum E : 16' to `short'. We want the real type of the
bit-field in this case, not some the integral equivalent. */
type = DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1));
if (TYPE_ALIAS_SET_KNOWN_P (type))
/* If we've already calculated the value, just return it. */
return TYPE_ALIAS_SET (type);
else if (TYPE_MAIN_VARIANT (type) != type)
/* The C standard specifically allows aliasing between
cv-qualified variants of types. */
TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
else if (TREE_CODE (type) == INTEGER_TYPE)
{
tree signed_variant;
/* The C standard specifically allows aliasing between signed and
unsigned variants of the same type. We treat the signed
variant as canonical. */
signed_variant = signed_type (type);
tree signed_variant = signed_type (t);
if (signed_variant != type)
TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
else if (signed_variant == signed_char_type_node)
if (signed_variant == signed_char_type_node)
/* The C standard guarantess that any object may be accessed
via an lvalue that has character type. We don't have to
check for unsigned_char_type_node or char_type_node because
we are specifically looking at the signed variant. */
TYPE_ALIAS_SET (type) = 0;
return 0;
else if (signed_variant != t)
return get_alias_set (signed_variant);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
/* Anything that can alias one of the array elements can alias
the entire array as well. */
TYPE_ALIAS_SET (type) = c_get_alias_set (TREE_TYPE (type));
else if (TREE_CODE (type) == FUNCTION_TYPE)
/* There are no objects of FUNCTION_TYPE, so there's no point in
using up an alias set for them. (There are, of course,
pointers and references to functions, but that's
different.) */
TYPE_ALIAS_SET (type) = 0;
else if (TREE_CODE (type) == RECORD_TYPE
|| TREE_CODE (type) == UNION_TYPE)
/* If TYPE is a struct or union type then we're reading or
writing an entire struct. Thus, we don't know anything about
aliasing. (In theory, such an access can only alias objects
whose type is the same as one of the fields, recursively, but
we don't yet make any use of that information.) */
TYPE_ALIAS_SET (type) = 0;
else if (POINTER_TYPE_P (type))
else if (POINTER_TYPE_P (t))
{
tree t;
tree t1;
/* Unfortunately, there is no canonical form of a pointer type.
In particular, if we have `typedef int I', then `int *', and
@ -3458,19 +3338,14 @@ c_get_alias_set (t)
can dereference IPP and CIPP. So, we ignore cv-qualifiers on
the pointed-to types. This issue has been reported to the
C++ committee. */
t = TYPE_MAIN_VARIANT (TREE_TYPE (type));
t = ((TREE_CODE (type) == POINTER_TYPE)
? build_pointer_type (t) : build_reference_type (t));
if (t != type)
TYPE_ALIAS_SET (type) = c_get_alias_set (t);
t1 = TYPE_MAIN_VARIANT (TREE_TYPE (t));
t1 = ((TREE_CODE (t) == POINTER_TYPE)
? build_pointer_type (t1) : build_reference_type (t1));
if (t1 != t)
return get_alias_set (t1);
}
if (! TYPE_ALIAS_SET_KNOWN_P (type))
/* TYPE is something we haven't seen before. Put it in a new
alias set. */
TYPE_ALIAS_SET (type) = new_alias_set ();
return TYPE_ALIAS_SET (type);
return -1;
}
/* Build tree nodes and builtin functions common to both C and C++ language
@ -3480,6 +3355,7 @@ c_get_alias_set (t)
NO_BUILTINS and NO_NONANSI_BUILTINS contain the respective values of
the language frontend flags flag_no_builtin and
flag_no_nonansi_builtin. */
void
c_common_nodes_and_builtins (cplus_mode, no_builtins, no_nonansi_builtins)
int cplus_mode, no_builtins, no_nonansi_builtins;

View File

@ -97,7 +97,7 @@ extern void decl_attributes PARAMS ((tree, tree, tree));
extern void init_function_format_info PARAMS ((void));
extern void check_function_format PARAMS ((tree, tree, tree));
extern void c_apply_type_quals_to_decl PARAMS ((int, tree));
extern int c_get_alias_set PARAMS ((tree));
extern HOST_WIDE_INT c_get_alias_set PARAMS ((tree));
/* Print an error message for invalid operands to arith operation CODE.
NOP_EXPR is used as a special case (see truthvalue_conversion). */
extern void binary_op_error PARAMS ((enum tree_code));

View File

@ -313,6 +313,7 @@ common_type (t1, t2)
return build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has one. */
t1 = build_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2));
record_component_aliases (t1);
return build_type_attribute_variant (t1, attributes);
}

View File

@ -256,6 +256,7 @@ void
setup_save_areas ()
{
int i, j, k;
unsigned int r;
HARD_REG_SET hard_regs_used;
/* Allocate space in the save area for the largest multi-register
@ -267,16 +268,13 @@ setup_save_areas ()
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0)
{
int regno = reg_renumber[i];
int endregno
unsigned int regno = reg_renumber[i];
unsigned int endregno
= regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i]));
int nregs = endregno - regno;
for (j = 0; j < nregs; j++)
{
if (call_used_regs[regno+j])
SET_HARD_REG_BIT (hard_regs_used, regno+j);
}
for (r = regno; r < endregno; r++)
if (call_used_regs[r])
SET_HARD_REG_BIT (hard_regs_used, r);
}
/* Now run through all the call-used hard-registers and allocate
@ -322,16 +320,24 @@ setup_save_areas ()
{
/* This should not depend on WORDS_BIG_ENDIAN.
The order of words in regs is the same as in memory. */
rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
rtx temp = gen_rtx_MEM (regno_save_mode[i + k][1],
XEXP (regno_save_mem[i][j], 0));
regno_save_mem[i+k][1]
regno_save_mem[i + k][1]
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
}
}
/* Now loop again and set the alias set of any save areas we made to
the alias set used to represent frame objects. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = MOVE_MAX_WORDS; j > 0; j--)
if (regno_save_mem[i][j] != 0)
MEM_ALIAS_SET (regno_save_mem[i][j]) = get_frame_alias_set ();
}
/* Find the places where hard regs are live across calls and save them. */
void
save_call_clobbered_regs ()
{

View File

@ -850,6 +850,7 @@ precompute_register_parameters (num_actuals, args, reg_parm_seen)
/* The argument list is the property of the called routine and it
may clobber it. If the fixed area has been used for previous
parameters, we must save and restore it. */
static rtx
save_fixed_argument_area (reg_parm_stack_space, argblock,
low_to_save, high_to_save)
@ -891,10 +892,11 @@ save_fixed_argument_area (reg_parm_stack_space, argblock,
save_mode = BLKmode;
#ifdef ARGS_GROW_DOWNWARD
stack_area = gen_rtx_MEM (save_mode,
memory_address (save_mode,
plus_constant (argblock,
- *high_to_save)));
stack_area
= gen_rtx_MEM (save_mode,
memory_address (save_mode,
plus_constant (argblock,
- *high_to_save)));
#else
stack_area = gen_rtx_MEM (save_mode,
memory_address (save_mode,
@ -1191,17 +1193,12 @@ initialize_argument_information (num_actuals, args, args_size, n_named_args,
}
copy = gen_rtx_MEM (BLKmode,
allocate_dynamic_stack_space (size_rtx,
NULL_RTX,
TYPE_ALIGN (type)));
allocate_dynamic_stack_space
(size_rtx, NULL_RTX, TYPE_ALIGN (type)));
set_mem_attributes (copy, type, 1);
}
else
{
int size = int_size_in_bytes (type);
copy = assign_stack_temp (TYPE_MODE (type), size, 0);
}
MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
copy = assign_temp (type, 0, 1, 0);
store_expr (args[i].tree_value, copy, 0);
*ecf_flags &= ~(ECF_CONST | ECF_PURE);
@ -1585,9 +1582,8 @@ compute_argument_addresses (args, argblock, num_actuals)
addr = plus_constant (addr, arg_offset);
args[i].stack = gen_rtx_MEM (args[i].mode, addr);
MEM_SET_IN_STRUCT_P
(args[i].stack,
AGGREGATE_TYPE_P (TREE_TYPE (args[i].tree_value)));
set_mem_attributes (args[i].stack,
TREE_TYPE (args[i].tree_value), 1);
if (GET_CODE (slot_offset) == CONST_INT)
addr = plus_constant (arg_reg, INTVAL (slot_offset));
@ -1596,6 +1592,8 @@ compute_argument_addresses (args, argblock, num_actuals)
addr = plus_constant (addr, arg_offset);
args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr);
set_mem_attributes (args[i].stack_slot,
TREE_TYPE (args[i].tree_value), 1);
}
}
}
@ -3058,11 +3056,11 @@ expand_call (exp, target, ignore)
{
if (target == 0 || GET_CODE (target) != MEM)
{
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
memory_address (TYPE_MODE (TREE_TYPE (exp)),
structure_value_addr));
MEM_SET_IN_STRUCT_P (target,
AGGREGATE_TYPE_P (TREE_TYPE (exp)));
target
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
memory_address (TYPE_MODE (TREE_TYPE (exp)),
structure_value_addr));
set_mem_attributes (target, exp, 1);
}
}
else if (pcc_struct_value)
@ -3072,7 +3070,7 @@ expand_call (exp, target, ignore)
never use this value more than once in one expression. */
target = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)),
copy_to_reg (valreg));
MEM_SET_IN_STRUCT_P (target, AGGREGATE_TYPE_P (TREE_TYPE (exp)));
set_mem_attributes (target, exp, 1);
}
/* Handle calls that return values in multiple non-contiguous locations.
The Irix 6 ABI has examples of this. */

View File

@ -1,3 +1,12 @@
Wed May 31 14:09:00 2000 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (decl.o): Include ../expr.h.
* decl.c (expr.h): Include.
(init_decl_processing): Call record_component_aliases for arrays.
(grokdeclarator): Likewise.
Set TREE_ADDRESSABLE for fields that aren't bitfields.
* tree.c (build_cplus_array_type_1): Call record_component_aliases.
2000-05-31 Mark Mitchell <mark@codesourcery.com>
* decl.c (build_cp_library_fn): Set DECL_CONTEXT.

View File

@ -256,7 +256,7 @@ lex.o : lex.c $(CXX_TREE_H) \
$(srcdir)/../output.h $(srcdir)/../mbchar.h $(GGC_H) \
$(srcdir)/../input.h operators.def
decl.o : decl.c $(CXX_TREE_H) $(srcdir)/../flags.h \
lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h \
lex.h decl.h $(srcdir)/../stack.h $(srcdir)/../output.h $(srcdir)/../expr.h \
$(srcdir)/../except.h $(srcdir)/../toplev.h \
$(srcdir)/../hash.h $(GGC_H) $(RTL_H) operators.def
decl2.o : decl2.c $(CXX_TREE_H) $(srcdir)/../flags.h \

View File

@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
@ -6455,10 +6456,14 @@ init_decl_processing ()
array type. */
char_array_type_node
= build_array_type (char_type_node, array_domain_type);
/* Likewise for arrays of ints. */
int_array_type_node
= build_array_type (integer_type_node, array_domain_type);
record_component_aliases (char_array_type_node);
record_component_aliases (int_array_type_node);
if (flag_new_abi)
delta_type_node = ptrdiff_type_node;
else if (flag_huge_objects)
@ -6522,6 +6527,7 @@ init_decl_processing ()
/* This is for wide string constants. */
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
record_component_aliases (wchar_array_type_node);
if (flag_vtable_thunks)
{
@ -11588,6 +11594,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
else
{
decl = build_decl (FIELD_DECL, declarator, type);
TREE_ADDRESSABLE (decl) = ! bitfield;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
DECL_MUTABLE_P (decl) = 1;

View File

@ -500,7 +500,10 @@ build_cplus_array_type_1 (elt_type, index_type)
TYPE_DOMAIN (t) = index_type;
}
else
t = build_array_type (elt_type, index_type);
{
t = build_array_type (elt_type, index_type);
record_component_aliases (t);
}
/* Push these needs up so that initialization takes place
more easily. */

View File

@ -628,6 +628,61 @@ validize_mem (ref)
return change_address (ref, GET_MODE (ref), XEXP (ref, 0));
}
/* Given REF, a MEM, and T, either the type of X or the expression
corresponding to REF, set the memory attributes. OBJECTP is nonzero
if we are making a new object of this type. */
void
set_mem_attributes (ref, t, objectp)
rtx ref;
tree t;
int objectp;
{
tree type = TYPE_P (t) ? t : TREE_TYPE (t);
/* Get the alias set from the expression or type (perhaps using a
front-end routine) and then copy bits from the type. */
MEM_ALIAS_SET (ref) = get_alias_set (t);
RTX_UNCHANGING_P (ref) = TYPE_READONLY (type);
MEM_VOLATILE_P (ref) = TYPE_VOLATILE (type);
MEM_IN_STRUCT_P (ref) = AGGREGATE_TYPE_P (type);
/* If we are making an object of this type, we know that it is a scalar if
the type is not an aggregate. */
if (objectp && ! AGGREGATE_TYPE_P (type))
MEM_SCALAR_P (ref) = 1;
/* If T is a type, this is all we can do. Otherwise, we may be able
to deduce some more information about the expression. */
if (TYPE_P (t))
return;
if (TREE_READONLY (t) || TREE_CODE_CLASS (TREE_CODE (t)) == 'c')
RTX_UNCHANGING_P (ref) = 1;
if (TREE_THIS_VOLATILE (t))
MEM_VOLATILE_P (ref) = 1;
/* Now see if we can say more about whether it's an aggregate or
scalar. If we already know it's an aggregate, don't bother. */
if (MEM_IN_STRUCT_P (ref))
return;
/* Now remove any NOPs: they don't change what the underlying object is.
Likewise for SAVE_EXPR. */
while (TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR
|| TREE_CODE (t) == NON_LVALUE_EXPR || TREE_CODE (t) == SAVE_EXPR)
t = TREE_OPERAND (t, 0);
/* Since we already know the type isn't an aggregate, if this is a decl,
it must be a scalar. Or if it is a reference into an aggregate,
this is part of an aggregate. Otherwise we don't know. */
if (DECL_P (t))
MEM_SCALAR_P (ref) = 1;
else if (TREE_CODE (t) == COMPONENT_REF || TREE_CODE (t) == ARRAY_REF
|| TREE_CODE (t) == BIT_FIELD_REF)
MEM_IN_STRUCT_P (ref) = 1;
}
/* Return a modified copy of X with its memory address copied
into a temporary register to protect it from side effects.
If X is not a MEM, it is returned unchanged (and not copied).
@ -638,25 +693,17 @@ stabilize (x)
rtx x;
{
register rtx addr;
if (GET_CODE (x) != MEM)
return x;
addr = XEXP (x, 0);
if (rtx_unstable_p (addr))
{
rtx temp = copy_all_regs (addr);
rtx mem;
if (GET_CODE (temp) != REG)
temp = copy_to_reg (temp);
mem = gen_rtx_MEM (GET_MODE (x), temp);
/* Mark returned memref with in_struct if it's in an array or
structure. Copy everything else from original memref. */
rtx temp = force_reg (Pmode, copy_all_regs (addr));
rtx mem = gen_rtx_MEM (GET_MODE (x), temp);
MEM_COPY_ATTRIBUTES (mem, x);
if (GET_CODE (addr) == PLUS)
MEM_SET_IN_STRUCT_P (mem, 1);
return mem;
}
return x;

View File

@ -115,16 +115,12 @@ struct move_by_pieces
rtx to_addr;
int autinc_to;
int explicit_inc_to;
int to_struct;
int to_readonly;
rtx from;
rtx from_addr;
int autinc_from;
int explicit_inc_from;
int from_struct;
int from_readonly;
int len;
int offset;
unsigned HOST_WIDE_INT len;
HOST_WIDE_INT offset;
int reverse;
};
@ -137,9 +133,8 @@ struct clear_by_pieces
rtx to_addr;
int autinc_to;
int explicit_inc_to;
int to_struct;
int len;
int offset;
unsigned HOST_WIDE_INT len;
HOST_WIDE_INT offset;
int reverse;
};
@ -148,10 +143,13 @@ extern struct obstack permanent_obstack;
static rtx get_push_address PARAMS ((int));
static rtx enqueue_insn PARAMS ((rtx, rtx));
static int move_by_pieces_ninsns PARAMS ((unsigned int, unsigned int));
static unsigned HOST_WIDE_INT move_by_pieces_ninsns
PARAMS ((unsigned HOST_WIDE_INT,
unsigned int));
static void move_by_pieces_1 PARAMS ((rtx (*) (rtx, ...), enum machine_mode,
struct move_by_pieces *));
static void clear_by_pieces PARAMS ((rtx, int, unsigned int));
static void clear_by_pieces PARAMS ((rtx, unsigned HOST_WIDE_INT,
unsigned int));
static void clear_by_pieces_1 PARAMS ((rtx (*) (rtx, ...),
enum machine_mode,
struct clear_by_pieces *));
@ -1381,7 +1379,7 @@ convert_modes (mode, oldmode, x, unsignedp)
void
move_by_pieces (to, from, len, align)
rtx to, from;
int len;
unsigned HOST_WIDE_INT len;
unsigned int align;
{
struct move_by_pieces data;
@ -1410,11 +1408,6 @@ move_by_pieces (to, from, len, align)
if (data.reverse) data.offset = len;
data.len = len;
data.to_struct = MEM_IN_STRUCT_P (to);
data.from_struct = MEM_IN_STRUCT_P (from);
data.to_readonly = RTX_UNCHANGING_P (to);
data.from_readonly = RTX_UNCHANGING_P (from);
/* If copying requires more than two move insns,
copy addresses to registers (to make displacements shorter)
and use post-increment if available. */
@ -1489,13 +1482,13 @@ move_by_pieces (to, from, len, align)
/* Return number of insns required to move L bytes by pieces.
ALIGN (in bytes) is maximum alignment we can assume. */
static int
static unsigned HOST_WIDE_INT
move_by_pieces_ninsns (l, align)
unsigned int l;
unsigned HOST_WIDE_INT l;
unsigned int align;
{
register int n_insns = 0;
unsigned int max_size = MOVE_MAX + 1;
unsigned HOST_WIDE_INT n_insns = 0;
unsigned HOST_WIDE_INT max_size = MOVE_MAX + 1;
if (! SLOW_UNALIGNED_ACCESS (word_mode, align)
|| align > MOVE_MAX * BITS_PER_UNIT || align >= BIGGEST_ALIGNMENT)
@ -1534,29 +1527,31 @@ move_by_pieces_1 (genfun, mode, data)
enum machine_mode mode;
struct move_by_pieces *data;
{
register int size = GET_MODE_SIZE (mode);
register rtx to1, from1;
unsigned int size = GET_MODE_SIZE (mode);
rtx to1, from1;
while (data->len >= size)
{
if (data->reverse) data->offset -= size;
if (data->reverse)
data->offset -= size;
to1 = (data->autinc_to
? gen_rtx_MEM (mode, data->to_addr)
: copy_rtx (change_address (data->to, mode,
plus_constant (data->to_addr,
data->offset))));
MEM_IN_STRUCT_P (to1) = data->to_struct;
RTX_UNCHANGING_P (to1) = data->to_readonly;
if (data->autinc_to)
{
to1 = gen_rtx_MEM (mode, data->to_addr);
MEM_COPY_ATTRIBUTES (to1, data->to);
}
else
to1 = change_address (data->to, mode,
plus_constant (data->to_addr, data->offset));
from1
= (data->autinc_from
? gen_rtx_MEM (mode, data->from_addr)
: copy_rtx (change_address (data->from, mode,
plus_constant (data->from_addr,
data->offset))));
MEM_IN_STRUCT_P (from1) = data->from_struct;
RTX_UNCHANGING_P (from1) = data->from_readonly;
if (data->autinc_from)
{
from1 = gen_rtx_MEM (mode, data->from_addr);
MEM_COPY_ATTRIBUTES (from1, data->from);
}
else
from1 = change_address (data->from, mode,
plus_constant (data->from_addr, data->offset));
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
@ -1564,12 +1559,14 @@ move_by_pieces_1 (genfun, mode, data)
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, from1));
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
if (HAVE_POST_INCREMENT && data->explicit_inc_from > 0)
emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
if (! data->reverse) data->offset += size;
if (! data->reverse)
data->offset += size;
data->len -= size;
}
@ -2243,12 +2240,12 @@ use_group_regs (call_fusage, regs)
static void
clear_by_pieces (to, len, align)
rtx to;
int len;
unsigned HOST_WIDE_INT len;
unsigned int align;
{
struct clear_by_pieces data;
rtx to_addr = XEXP (to, 0);
unsigned int max_size = MOVE_MAX_PIECES + 1;
unsigned HOST_WIDE_INT max_size = MOVE_MAX_PIECES + 1;
enum machine_mode mode = VOIDmode, tmode;
enum insn_code icode;
@ -2265,8 +2262,6 @@ clear_by_pieces (to, len, align)
if (data.reverse) data.offset = len;
data.len = len;
data.to_struct = MEM_IN_STRUCT_P (to);
/* If copying requires more than two move insns,
copy addresses to registers (to make displacements shorter)
and use post-increment if available. */
@ -2285,13 +2280,16 @@ clear_by_pieces (to, len, align)
data.autinc_to = 1;
data.explicit_inc_to = -1;
}
if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse && ! data.autinc_to)
if (USE_STORE_POST_INCREMENT (mode) && ! data.reverse
&& ! data.autinc_to)
{
data.to_addr = copy_addr_to_reg (to_addr);
data.autinc_to = 1;
data.explicit_inc_to = 1;
}
if (!data.autinc_to && CONSTANT_P (to_addr))
if ( !data.autinc_to && CONSTANT_P (to_addr))
data.to_addr = copy_addr_to_reg (to_addr);
}
@ -2334,28 +2332,33 @@ clear_by_pieces_1 (genfun, mode, data)
enum machine_mode mode;
struct clear_by_pieces *data;
{
register int size = GET_MODE_SIZE (mode);
register rtx to1;
unsigned int size = GET_MODE_SIZE (mode);
rtx to1;
while (data->len >= size)
{
if (data->reverse) data->offset -= size;
if (data->reverse)
data->offset -= size;
to1 = (data->autinc_to
? gen_rtx_MEM (mode, data->to_addr)
: copy_rtx (change_address (data->to, mode,
plus_constant (data->to_addr,
data->offset))));
MEM_IN_STRUCT_P (to1) = data->to_struct;
if (data->autinc_to)
{
to1 = gen_rtx_MEM (mode, data->to_addr);
MEM_COPY_ATTRIBUTES (to1, data->to);
}
else
to1 = change_address (data->to, mode,
plus_constant (data->to_addr, data->offset));
if (HAVE_PRE_DECREMENT && data->explicit_inc_to < 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
emit_insn ((*genfun) (to1, const0_rtx));
if (HAVE_POST_INCREMENT && data->explicit_inc_to > 0)
emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
if (! data->reverse) data->offset += size;
if (! data->reverse)
data->offset += size;
data->len -= size;
}
@ -2627,17 +2630,17 @@ emit_move_insn_1 (x, y)
regardless of machine's endianness. */
#ifdef STACK_GROWS_DOWNWARD
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(gen_rtx_MEM (submode, (XEXP (x, 0))),
(gen_rtx_MEM (submode, XEXP (x, 0)),
gen_imagpart (submode, y)));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(gen_rtx_MEM (submode, (XEXP (x, 0))),
(gen_rtx_MEM (submode, XEXP (x, 0)),
gen_realpart (submode, y)));
#else
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(gen_rtx_MEM (submode, (XEXP (x, 0))),
(gen_rtx_MEM (submode, XEXP (x, 0)),
gen_realpart (submode, y)));
emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
(gen_rtx_MEM (submode, (XEXP (x, 0))),
(gen_rtx_MEM (submode, XEXP (x, 0)),
gen_imagpart (submode, y)));
#endif
}
@ -2866,7 +2869,7 @@ push_block (size, extra, below)
- INTVAL (size) - (below ? 0 : extra));
else if (extra != 0 && !below)
temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
negate_rtx (Pmode, plus_constant (size, extra)));
negate_rtx (Pmode, plus_constant (size, extra)));
else
temp = gen_rtx_PLUS (Pmode, virtual_outgoing_args_rtx,
negate_rtx (Pmode, size));
@ -3105,6 +3108,11 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
if (GET_CODE (size) == CONST_INT
&& MOVE_BY_PIECES_P ((unsigned) INTVAL (size), align))
{
rtx target = gen_rtx_MEM (BLKmode, temp);
if (type != 0)
set_mem_attributes (target, type, 1);
move_by_pieces (gen_rtx_MEM (BLKmode, temp), xinner,
INTVAL (size), align);
goto ret;
@ -3115,6 +3123,9 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
enum machine_mode mode;
rtx target = gen_rtx_MEM (BLKmode, temp);
if (type != 0)
set_mem_attributes (target, type, 1);
for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
mode != VOIDmode;
mode = GET_MODE_WIDER_MODE (mode))
@ -3251,6 +3262,7 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
{
rtx addr;
rtx target = NULL_RTX;
rtx dest;
/* Push padding now if padding above and stack grows down,
or if padding below and stack grows up.
@ -3279,7 +3291,11 @@ emit_push_insn (x, mode, type, size, align, partial, reg, extra,
target = addr;
}
emit_move_insn (gen_rtx_MEM (mode, addr), x);
dest = gen_rtx_MEM (mode, addr);
if (type != 0)
set_mem_attributes (dest, type, 1);
emit_move_insn (dest, x);
if (current_function_check_memory_usage && ! in_check_memory_usage)
{
@ -3994,6 +4010,10 @@ store_expr (exp, target, want_value)
if (size != const0_rtx)
{
rtx dest = gen_rtx_MEM (BLKmode, addr);
MEM_COPY_ATTRIBUTES (dest, target);
/* Be sure we can write on ADDR. */
in_check_memory_usage = 1;
if (current_function_check_memory_usage)
@ -4003,7 +4023,7 @@ store_expr (exp, target, want_value)
GEN_INT (MEMORY_USE_WO),
TYPE_MODE (integer_type_node));
in_check_memory_usage = 0;
clear_storage (gen_rtx_MEM (BLKmode, addr), size, align);
clear_storage (target, size, align);
}
if (label)
@ -5980,10 +6000,11 @@ expand_expr (exp, target, tmode, modifier)
abort ();
addr = XEXP (DECL_RTL (exp), 0);
if (GET_CODE (addr) == MEM)
addr = gen_rtx_MEM (Pmode,
fix_lexical_addr (XEXP (addr, 0), exp));
addr = change_address (addr, Pmode,
fix_lexical_addr (XEXP (addr, 0), exp));
else
addr = fix_lexical_addr (addr, exp);
temp = change_address (DECL_RTL (exp), mode, addr);
}
@ -6418,7 +6439,6 @@ expand_expr (exp, target, tmode, modifier)
case INDIRECT_REF:
{
tree exp1 = TREE_OPERAND (exp, 0);
tree exp2;
tree index;
tree string = string_constant (exp1, &index);
@ -6456,19 +6476,7 @@ expand_expr (exp, target, tmode, modifier)
}
temp = gen_rtx_MEM (mode, op0);
/* If address was computed by addition,
mark this as an element of an aggregate. */
if (TREE_CODE (exp1) == PLUS_EXPR
|| (TREE_CODE (exp1) == SAVE_EXPR
&& TREE_CODE (TREE_OPERAND (exp1, 0)) == PLUS_EXPR)
|| AGGREGATE_TYPE_P (TREE_TYPE (exp))
|| (TREE_CODE (exp1) == ADDR_EXPR
&& (exp2 = TREE_OPERAND (exp1, 0))
&& AGGREGATE_TYPE_P (TREE_TYPE (exp2))))
MEM_SET_IN_STRUCT_P (temp, 1);
MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) | flag_volatile;
MEM_ALIAS_SET (temp) = get_alias_set (exp);
set_mem_attributes (temp, exp, 0);
/* It is incorrect to set RTX_UNCHANGING_P from TREE_READONLY
here, because, in C and C++, the fact that a location is accessed
@ -6893,13 +6901,10 @@ expand_expr (exp, target, tmode, modifier)
plus_constant (XEXP (op0, 0),
(bitpos / BITS_PER_UNIT)));
if (GET_CODE (op0) == MEM)
MEM_ALIAS_SET (op0) = get_alias_set (exp);
set_mem_attributes (op0, exp, 0);
if (GET_CODE (XEXP (op0, 0)) == REG)
mark_reg_pointer (XEXP (op0, 0), alignment);
MEM_SET_IN_STRUCT_P (op0, 1);
MEM_VOLATILE_P (op0) |= volatilep;
if (mode == mode1 || mode1 == BLKmode || mode1 == tmode
|| modifier == EXPAND_CONST_ADDRESS

View File

@ -94,8 +94,8 @@ struct args_size
#define ADD_PARM_SIZE(TO, INC) \
{ tree inc = (INC); \
if (TREE_CODE (inc) == INTEGER_CST) \
(TO).constant += TREE_INT_CST_LOW (inc); \
if (host_integerp (inc, 0)) \
(TO).constant += tree_low_cst (inc, 0); \
else if ((TO).var == 0) \
(TO).var = inc; \
else \
@ -103,8 +103,8 @@ struct args_size
#define SUB_PARM_SIZE(TO, DEC) \
{ tree dec = (DEC); \
if (TREE_CODE (dec) == INTEGER_CST) \
(TO).constant -= TREE_INT_CST_LOW (dec); \
if (host_integerp (dec, 0)) \
(TO).constant -= tree_low_cst (dec, 0); \
else if ((TO).var == 0) \
(TO).var = size_binop (MINUS_EXPR, ssize_int (0), dec); \
else \
@ -915,7 +915,16 @@ extern rtx expand_builtin_va_arg PARAMS ((tree, tree));
extern rtx expand_builtin_setjmp PARAMS ((rtx, rtx, rtx, rtx));
extern void expand_builtin_longjmp PARAMS ((rtx, rtx));
extern rtx expand_builtin_saveregs PARAMS ((void));
extern int get_varargs_alias_set PARAMS ((void));
extern HOST_WIDE_INT get_varargs_alias_set PARAMS ((void));
extern HOST_WIDE_INT get_frame_alias_set PARAMS ((void));
extern void record_base_value PARAMS ((unsigned int, rtx, int));
extern void record_alias_subset PARAMS ((HOST_WIDE_INT,
HOST_WIDE_INT));
#ifdef TREE_CODE
extern HOST_WIDE_INT get_alias_set PARAMS ((tree));
extern HOST_WIDE_INT (*lang_get_alias_set) PARAMS ((tree));
#endif
extern HOST_WIDE_INT new_alias_set PARAMS ((void));
/* Functions from expr.c: */
@ -1013,10 +1022,9 @@ extern void emit_push_insn PARAMS ((rtx, enum machine_mode, tree, rtx,
int, rtx));
/* Emit library call. */
extern void emit_library_call PARAMS ((rtx orgfun, int no_queue,
enum machine_mode outmode, int nargs, ...));
extern rtx emit_library_call_value PARAMS ((rtx orgfun, rtx value, int no_queue,
enum machine_mode outmode, int nargs, ...));
extern void emit_library_call PARAMS ((rtx, int, enum machine_mode, int, ...));
extern rtx emit_library_call_value PARAMS ((rtx, rtx, int, enum machine_mode,
int, ...));
/* Expand an assignment that stores the value of FROM into TO. */
extern rtx expand_assignment PARAMS ((tree, tree, int, int));
@ -1100,10 +1108,17 @@ extern rtx prepare_call_address PARAMS ((rtx, tree, rtx *, int));
extern rtx expand_call PARAMS ((tree, rtx, int));
extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree, rtx, int));
extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx, rtx, rtx, int));
extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree, struct args_size *, struct args_size *, struct args_size *, struct args_size *));
extern rtx expand_shift PARAMS ((enum tree_code, enum machine_mode, rtx, tree,
rtx, int));
extern rtx expand_divmod PARAMS ((int, enum tree_code, enum machine_mode, rtx,
rtx, rtx, int));
extern void locate_and_pad_parm PARAMS ((enum machine_mode, tree, int, tree,
struct args_size *,
struct args_size *,
struct args_size *,
struct args_size *));
extern rtx expand_inline_function PARAMS ((tree, tree, rtx, int, tree, rtx));
/* Return the CODE_LABEL rtx for a LABEL_DECL, creating it if necessary. */
extern rtx label_rtx PARAMS ((tree));
#endif
@ -1132,9 +1147,15 @@ extern rtx change_address PARAMS ((rtx, enum machine_mode, rtx));
/* Return a memory reference like MEMREF, but which is known to have a
valid address. */
extern rtx validize_mem PARAMS ((rtx));
#ifdef TREE_CODE
/* Given REF, a MEM, and T, either the type of X or the expression
corresponding to REF, set the memory attributes. OBJECTP is nonzero
if we are making a new object of this type. */
extern void set_mem_attributes PARAMS ((rtx, tree, int));
#endif
/* Assemble the static constant template for function entry trampolines. */
extern rtx assemble_trampoline_template PARAMS ((void));

View File

@ -204,7 +204,7 @@ struct temp_slot
imposed on the memory. For example, if the stack slot is the
call frame for an inline functioned, we have no idea what alias
sets will be assigned to various pieces of the call frame. */
int alias_set;
HOST_WIDE_INT alias_set;
/* The value of `sequence_rtl_expr' when this temporary is allocated. */
tree rtl_expr;
/* Non-zero if this temporary is currently in use. */
@ -628,6 +628,7 @@ assign_stack_local_1 (mode, size, align, function)
/* Wrapper around assign_stack_local_1; assign a local stack slot for the
current function. */
rtx
assign_stack_local (mode, size, align)
enum machine_mode mode;
@ -662,7 +663,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
tree type;
{
int align;
int alias_set;
HOST_WIDE_INT alias_set;
struct temp_slot *p, *best_p = 0;
/* If SIZE is -1 it means that somebody tried to allocate a temporary
@ -684,6 +685,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
if (! type)
type = type_for_mode (mode, 0);
if (type)
align = LOCAL_ALIGNMENT (type, align);
@ -693,7 +695,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
for (p = temp_slots; p; p = p->next)
if (p->align >= align && p->size >= size && GET_MODE (p->slot) == mode
&& ! p->in_use
&& (!flag_strict_aliasing
&& (! flag_strict_aliasing
|| (alias_set && p->alias_set == alias_set))
&& (best_p == 0 || best_p->size > p->size
|| (best_p->size == p->size && best_p->align > p->align)))
@ -712,11 +714,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
/* If there are enough aligned bytes left over, make them into a new
temp_slot so that the extra bytes don't get wasted. Do this only
for BLKmode slots, so that we can be sure of the alignment. */
if (GET_MODE (best_p->slot) == BLKmode
/* We can't split slots if -fstrict-aliasing because the
information about the alias set for the new slot will be
lost. */
&& !flag_strict_aliasing)
if (GET_MODE (best_p->slot) == BLKmode)
{
int alignment = best_p->align / BITS_PER_UNIT;
HOST_WIDE_INT rounded_size = CEIL_ROUND (size, alignment);
@ -734,6 +732,7 @@ assign_stack_temp_for_type (mode, size, keep, type)
p->align = best_p->align;
p->address = 0;
p->rtl_expr = 0;
p->alias_set = best_p->alias_set;
p->next = temp_slots;
temp_slots = p;
@ -824,7 +823,11 @@ assign_stack_temp_for_type (mode, size, keep, type)
RTX_UNCHANGING_P (p->slot) = 0;
MEM_IN_STRUCT_P (p->slot) = 0;
MEM_SCALAR_P (p->slot) = 0;
MEM_ALIAS_SET (p->slot) = 0;
MEM_ALIAS_SET (p->slot) = alias_set;
if (type != 0)
MEM_SET_IN_STRUCT_P (p->slot, AGGREGATE_TYPE_P (type));
return p->slot;
}
@ -875,11 +878,10 @@ assign_temp (type, keep, memory_required, dont_promote)
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
&& TREE_CODE (TYPE_ARRAY_MAX_SIZE (type)) == INTEGER_CST)
size = TREE_INT_CST_LOW (TYPE_ARRAY_MAX_SIZE (type));
&& host_integerp (TYPE_ARRAY_MAX_SIZE (type), 1))
size = tree_low_cst (TYPE_ARRAY_MAX_SIZE (type), 1);
tmp = assign_stack_temp_for_type (mode, size, keep, type);
MEM_SET_IN_STRUCT_P (tmp, AGGREGATE_TYPE_P (type));
return tmp;
}
@ -1397,8 +1399,12 @@ put_var_into_stack (decl)
else
put_reg_into_stack (function, reg, TREE_TYPE (decl),
promoted_mode, decl_mode,
TREE_SIDE_EFFECTS (decl), 0,
TREE_USED (decl) || DECL_INITIAL (decl) != 0,
(TREE_CODE (decl) != SAVE_EXPR
&& TREE_THIS_VOLATILE (decl)),
0,
(TREE_USED (decl)
|| (TREE_CODE (decl) != SAVE_EXPR
&& DECL_INITIAL (decl) != 0)),
0);
}
else if (GET_CODE (reg) == CONCAT)
@ -2840,9 +2846,14 @@ put_addressof_into_stack (r, ht)
abort ();
put_reg_into_stack (0, reg, TREE_TYPE (decl), GET_MODE (reg),
DECL_MODE (decl), TREE_SIDE_EFFECTS (decl),
GET_MODE (reg),
(TREE_CODE (decl) != SAVE_EXPR
&& TREE_THIS_VOLATILE (decl)),
ADDRESSOF_REGNO (r),
TREE_USED (decl) || DECL_INITIAL (decl) != 0, ht);
(TREE_USED (decl)
|| (TREE_CODE (decl) != SAVE_EXPR
&& DECL_INITIAL (decl) != 0)),
ht);
}
/* List of replacements made below in purge_addressof_1 when creating
@ -4168,7 +4179,6 @@ assign_parms (fndecl)
for (parm = fnargs; parm; parm = TREE_CHAIN (parm))
{
int aggregate = AGGREGATE_TYPE_P (TREE_TYPE (parm));
struct args_size stack_offset;
struct args_size arg_size;
int passed_pointer = 0;
@ -4325,12 +4335,7 @@ assign_parms (fndecl)
internal_arg_pointer,
offset_rtx));
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. Likewise if it
is readonly. */
MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
RTX_UNCHANGING_P (stack_parm) = TREE_READONLY (parm);
MEM_ALIAS_SET (stack_parm) = get_alias_set (parm);
set_mem_attributes (stack_parm, parm, 1);
}
/* If this parameter was passed both in registers and in the stack,
@ -4435,38 +4440,6 @@ assign_parms (fndecl)
&& nominal_mode != BLKmode && nominal_mode != passed_mode)
stack_parm = 0;
#if 0
/* Now adjust STACK_PARM to the mode and precise location
where this parameter should live during execution,
if we discover that it must live in the stack during execution.
To make debuggers happier on big-endian machines, we store
the value in the last bytes of the space available. */
if (nominal_mode != BLKmode && nominal_mode != passed_mode
&& stack_parm != 0)
{
rtx offset_rtx;
if (BYTES_BIG_ENDIAN
&& GET_MODE_SIZE (nominal_mode) < UNITS_PER_WORD)
stack_offset.constant += (GET_MODE_SIZE (passed_mode)
- GET_MODE_SIZE (nominal_mode));
offset_rtx = ARGS_SIZE_RTX (stack_offset);
if (offset_rtx == const0_rtx)
stack_parm = gen_rtx_MEM (nominal_mode, internal_arg_pointer);
else
stack_parm = gen_rtx_MEM (nominal_mode,
gen_rtx_PLUS (Pmode,
internal_arg_pointer,
offset_rtx));
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
}
#endif /* 0 */
/* ENTRY_PARM is an RTX for the parameter as it arrives,
in the mode in which it arrives.
STACK_PARM is an RTX for a stack slot where the parameter can live
@ -4506,18 +4479,12 @@ assign_parms (fndecl)
stack_parm
= assign_stack_local (GET_MODE (entry_parm),
size_stored, 0);
/* If this is a memory ref that contains aggregate
components, mark it as such for cse and loop optimize. */
MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
set_mem_attributes (stack_parm, parm, 1);
}
else if (PARM_BOUNDARY % BITS_PER_WORD != 0)
abort ();
if (TREE_READONLY (parm))
RTX_UNCHANGING_P (stack_parm) = 1;
/* Handle calls that pass values in multiple non-contiguous
locations. The Irix 6 ABI has examples of this. */
if (GET_CODE (entry_parm) == PARALLEL)
@ -4566,7 +4533,7 @@ assign_parms (fndecl)
{
DECL_RTL (parm)
= gen_rtx_MEM (TYPE_MODE (TREE_TYPE (passed_type)), parmreg);
MEM_SET_IN_STRUCT_P (DECL_RTL (parm), aggregate);
set_mem_attributes (DECL_RTL (parm), parm, 1);
}
else
DECL_RTL (parm) = parmreg;
@ -4672,8 +4639,7 @@ assign_parms (fndecl)
else
copy = assign_stack_temp (TYPE_MODE (type),
int_size_in_bytes (type), 1);
MEM_SET_IN_STRUCT_P (copy, AGGREGATE_TYPE_P (type));
RTX_UNCHANGING_P (copy) = TREE_READONLY (parm);
set_mem_attributes (copy, parm);
store_expr (parm, copy, 0);
emit_move_insn (parmreg, XEXP (copy, 0));
@ -4824,9 +4790,7 @@ assign_parms (fndecl)
stack_parm
= assign_stack_local (GET_MODE (entry_parm),
GET_MODE_SIZE (GET_MODE (entry_parm)), 0);
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
MEM_SET_IN_STRUCT_P (stack_parm, aggregate);
set_mem_attributes (stack_parm, parm, 1);
}
if (promoted_mode != nominal_mode)
@ -4863,19 +4827,12 @@ assign_parms (fndecl)
if (parm == function_result_decl)
{
tree result = DECL_RESULT (fndecl);
tree restype = TREE_TYPE (result);
DECL_RTL (result)
= gen_rtx_MEM (DECL_MODE (result), DECL_RTL (parm));
MEM_SET_IN_STRUCT_P (DECL_RTL (result),
AGGREGATE_TYPE_P (restype));
set_mem_attributes (DECL_RTL (result), result, 1);
}
if (TREE_THIS_VOLATILE (parm))
MEM_VOLATILE_P (DECL_RTL (parm)) = 1;
if (TREE_READONLY (parm))
RTX_UNCHANGING_P (DECL_RTL (parm)) = 1;
}
/* Output all parameter conversion instructions (possibly including calls)
@ -5398,7 +5355,9 @@ fix_lexical_addr (addr, var)
addr = fix_lexical_addr (XEXP (fp->x_arg_pointer_save_area, 0), var);
addr = memory_address (Pmode, addr);
base = copy_to_reg (gen_rtx_MEM (Pmode, addr));
base = gen_rtx_MEM (Pmode, addr);
MEM_ALIAS_SET (base) = get_frame_alias_set ();
base = copy_to_reg (base);
#else
displacement += (FIRST_PARM_OFFSET (context) - STARTING_FRAME_OFFSET);
base = lookup_static_chain (var);
@ -6149,10 +6108,8 @@ expand_function_start (subr, parms_have_cleanups)
{
DECL_RTL (DECL_RESULT (subr))
= gen_rtx_MEM (DECL_MODE (DECL_RESULT (subr)), value_address);
MEM_SET_IN_STRUCT_P (DECL_RTL (DECL_RESULT (subr)),
AGGREGATE_TYPE_P (TREE_TYPE
(DECL_RESULT
(subr))));
set_mem_attributes (DECL_RTL (DECL_RESULT (subr)),
DECL_RESULT (subr), 1);
}
}
else if (DECL_MODE (DECL_RESULT (subr)) == VOIDmode)
@ -6247,9 +6204,9 @@ expand_function_start (subr, parms_have_cleanups)
#ifdef FRAME_GROWS_DOWNWARD
last_ptr = plus_constant (last_ptr, - GET_MODE_SIZE (Pmode));
#endif
last_ptr = copy_to_reg (gen_rtx_MEM (Pmode,
memory_address (Pmode,
last_ptr)));
last_ptr = gen_rtx_MEM (Pmode, memory_address (Pmode, last_ptr));
MEM_ALIAS_SET (last_ptr) = get_frame_alias_set ();
last_ptr = copy_to_reg (last_ptr);
/* If we are not optimizing, ensure that we know that this
piece of context is live over the entire function. */

View File

@ -1939,11 +1939,10 @@ mode_independent_operand (op, mode)
return 0;
}
/* Given an operand OP that is a valid memory reference
which satisfies offsettable_memref_p,
return a new memory reference whose address has been adjusted by OFFSET.
OFFSET should be positive and less than the size of the object referenced.
*/
/* Given an operand OP that is a valid memory reference which
satisfies offsettable_memref_p, return a new memory reference whose
address has been adjusted by OFFSET. OFFSET should be positive and
less than the size of the object referenced. */
rtx
adj_offsettable_operand (op, offset)
@ -1961,7 +1960,7 @@ adj_offsettable_operand (op, offset)
{
new = gen_rtx_MEM (GET_MODE (op),
plus_constant_for_output (y, offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
@ -1981,7 +1980,7 @@ adj_offsettable_operand (op, offset)
}
new = gen_rtx_MEM (GET_MODE (op), plus_constant_for_output (y, offset));
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (op);
MEM_COPY_ATTRIBUTES (new, op);
return new;
}
abort ();

View File

@ -2234,6 +2234,8 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta)
for (ml = memlist; ml ; ml = ml->next)
{
HOST_WIDE_INT c = ml->sp_offset - delta;
rtx new = gen_rtx_MEM (GET_MODE (*ml->mem),
plus_constant (stack_pointer_rtx, c));
/* Don't reference memory below the stack pointer. */
if (c < 0)
@ -2242,9 +2244,8 @@ try_apply_stack_adjustment (insn, memlist, new_adjust, delta)
return 0;
}
validate_change (ml->insn, ml->mem,
gen_rtx_MEM (GET_MODE (*ml->mem),
plus_constant (stack_pointer_rtx, c)), 1);
MEM_COPY_ATTRIBUTES (new, *ml->mem);
validate_change (ml->insn, ml->mem, new, 1);
}
if (apply_change_group ())

View File

@ -860,10 +860,20 @@ push_reload (in, out, inloc, outloc, class,
{
if (GET_CODE (XEXP (in, 0)) == POST_INC
|| GET_CODE (XEXP (in, 0)) == POST_DEC)
in = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0));
{
rtx new = gen_rtx_MEM (GET_MODE (in), XEXP (XEXP (in, 0), 0));
MEM_COPY_ATTRIBUTES (new, in);
in = new;
}
if (GET_CODE (XEXP (in, 0)) == PRE_INC
|| GET_CODE (XEXP (in, 0)) == PRE_DEC)
out = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0));
{
rtx new = gen_rtx_MEM (GET_MODE (out), XEXP (XEXP (out, 0), 0));
MEM_COPY_ATTRIBUTES (new, out);
out = new;
}
}
/* If we are reloading a (SUBREG constant ...), really reload just the
@ -4344,7 +4354,7 @@ make_memloc (ad, regno)
tem = copy_rtx (tem);
tem = gen_rtx_MEM (GET_MODE (ad), tem);
RTX_UNCHANGING_P (tem) = RTX_UNCHANGING_P (regno_reg_rtx[regno]);
MEM_COPY_ATTRIBUTES (tem, reg_equiv_memory_loc[regno]);
return tem;
}

View File

@ -1913,13 +1913,18 @@ alter_reg (i, from_reg)
adjust = inherent_size - total_size;
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
/* Nothing can alias this slot except this pseudo. */
MEM_ALIAS_SET (x) = new_alias_set ();
}
/* Reuse a stack slot if possible. */
else if (spill_stack_slot[from_reg] != 0
&& spill_stack_slot_width[from_reg] >= total_size
&& (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
>= inherent_size))
x = spill_stack_slot[from_reg];
/* Allocate a bigger slot. */
else
{
@ -1927,6 +1932,7 @@ alter_reg (i, from_reg)
and for total size. */
enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
rtx stack_slot;
if (spill_stack_slot[from_reg])
{
if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
@ -1935,10 +1941,18 @@ alter_reg (i, from_reg)
if (spill_stack_slot_width[from_reg] > total_size)
total_size = spill_stack_slot_width[from_reg];
}
/* Make a slot with that size. */
x = assign_stack_local (mode, total_size,
inherent_size == total_size ? 0 : -1);
stack_slot = x;
/* All pseudos mapped to this slot can alias each other. */
if (spill_stack_slot[from_reg])
MEM_ALIAS_SET (x) = MEM_ALIAS_SET (spill_stack_slot[from_reg]);
else
MEM_ALIAS_SET (x) = new_alias_set ();
if (BYTES_BIG_ENDIAN)
{
/* Cancel the big-endian correction done in assign_stack_local.
@ -1952,6 +1966,7 @@ alter_reg (i, from_reg)
MODE_INT, 1),
plus_constant (XEXP (x, 0), adjust));
}
spill_stack_slot[from_reg] = stack_slot;
spill_stack_slot_width[from_reg] = total_size;
}
@ -1965,16 +1980,11 @@ alter_reg (i, from_reg)
wrong mode, make a new stack slot. */
if (adjust != 0 || GET_MODE (x) != GET_MODE (regno_reg_rtx[i]))
{
x = gen_rtx_MEM (GET_MODE (regno_reg_rtx[i]),
plus_constant (XEXP (x, 0), adjust));
rtx new = gen_rtx_MEM (GET_MODE (regno_reg_rtx[i]),
plus_constant (XEXP (x, 0), adjust));
/* If this was shared among registers, must ensure we never
set it readonly since that can cause scheduling
problems. Note we would only have in this adjustment
case in any event, since the code above doesn't set it. */
if (from_reg == -1)
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
MEM_COPY_ATTRIBUTES (new, x);
x = new;
}
/* Save the stack slot for later. */
@ -2496,9 +2506,7 @@ eliminate_regs (x, mem_mode, insn)
if (new != XEXP (x, 0))
{
new = gen_rtx_MEM (GET_MODE (x), new);
new->volatil = x->volatil;
new->unchanging = x->unchanging;
new->in_struct = x->in_struct;
MEM_COPY_ATTRIBUTES (new, x);
return new;
}
else

View File

@ -628,7 +628,7 @@ DEF_RTL_EXPR(CONCAT, "concat", "ee", 'o')
/* A memory location; operand is the address. Can be nested inside a
VOLATILE. The second operand is the alias set to which this MEM
belongs. We use `0' instead of `i' for this field so that the
belongs. We use `0' instead of `w' for this field so that the
field need not be specified in machine descriptions. */
DEF_RTL_EXPR(MEM, "mem", "e0", 'o')

View File

@ -746,8 +746,10 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
#define ASM_OPERANDS_INPUT_CONSTRAINT_VEC(RTX) XCVEC ((RTX), 4, ASM_OPERANDS)
#define ASM_OPERANDS_INPUT(RTX, N) XCVECEXP ((RTX), 3, (N), ASM_OPERANDS)
#define ASM_OPERANDS_INPUT_LENGTH(RTX) XCVECLEN ((RTX), 3, ASM_OPERANDS)
#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0)
#define ASM_OPERANDS_INPUT_MODE(RTX, N) GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS))
#define ASM_OPERANDS_INPUT_CONSTRAINT(RTX, N) \
XSTR (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS), 0)
#define ASM_OPERANDS_INPUT_MODE(RTX, N) \
GET_MODE (XCVECEXP ((RTX), 4, (N), ASM_OPERANDS))
#define ASM_OPERANDS_SOURCE_FILE(RTX) XCSTR ((RTX), 5, ASM_OPERANDS)
#define ASM_OPERANDS_SOURCE_LINE(RTX) XCINT ((RTX), 6, ASM_OPERANDS)
@ -755,22 +757,15 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
Also in an ASM_OPERANDS rtx. */
#define MEM_VOLATILE_P(RTX) ((RTX)->volatil)
/* For a MEM rtx, 1 if it refers to a field of an aggregate. If zero,
RTX may or may not refer to a field of an aggregate. */
/* For a MEM rtx, 1 if it refers to an aggregate, either to the
aggregate itself of to a field of the aggregate. If zero, RTX may
or may not be such a refrence. */
#define MEM_IN_STRUCT_P(RTX) ((RTX)->in_struct)
/* For a MEM rtx, 1 if it refers to a scalar. If zero, RTX may or may
not refer to a scalar.*/
#define MEM_SCALAR_P(RTX) ((RTX)->frame_related)
/* Copy the attributes that apply to memory locations from RHS to LHS. */
#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
(MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \
MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS), \
RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS))
/* If VAL is non-zero, set MEM_IN_STRUCT_P and clear MEM_SCALAR_P in
RTX. Otherwise, vice versa. Use this macro only when you are
*sure* that you know that the MEM is in a structure, or is a
@ -797,7 +792,15 @@ extern const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS];
some front-ends, these numbers may correspond in some way to types,
or other language-level entities, but they need not, and the
back-end makes no such assumptions. */
#define MEM_ALIAS_SET(RTX) XCINT(RTX, 1, MEM)
#define MEM_ALIAS_SET(RTX) XCWINT(RTX, 1, MEM)
/* Copy the attributes that apply to memory locations from RHS to LHS. */
#define MEM_COPY_ATTRIBUTES(LHS, RHS) \
(MEM_VOLATILE_P (LHS) = MEM_VOLATILE_P (RHS), \
MEM_IN_STRUCT_P (LHS) = MEM_IN_STRUCT_P (RHS), \
MEM_SCALAR_P (LHS) = MEM_SCALAR_P (RHS), \
MEM_ALIAS_SET (LHS) = MEM_ALIAS_SET (RHS), \
RTX_UNCHANGING_P (LHS) = RTX_UNCHANGING_P (RHS))
/* For a LABEL_REF, 1 means that this reference is to a label outside the
loop containing the reference. */
@ -1645,7 +1648,9 @@ extern int preserve_subexpressions_p PARAMS ((void));
/* In expr.c */
extern void init_expr_once PARAMS ((void));
extern void move_by_pieces PARAMS ((rtx, rtx, int, unsigned int));
extern void move_by_pieces PARAMS ((rtx, rtx,
unsigned HOST_WIDE_INT,
unsigned int));
/* In flow.c */
extern void allocate_bb_life_data PARAMS ((void));
@ -1821,9 +1826,6 @@ extern void mark_constant_function PARAMS ((void));
extern void init_alias_once PARAMS ((void));
extern void init_alias_analysis PARAMS ((void));
extern void end_alias_analysis PARAMS ((void));
extern void record_base_value PARAMS ((unsigned int, rtx, int));
extern void record_alias_subset PARAMS ((int, int));
extern rtx addr_side_effect_eval PARAMS ((rtx, int, int));
/* In sibcall.c */

View File

@ -3792,7 +3792,8 @@ expand_decl (decl)
/* An initializer is going to decide the size of this array.
Until we know the size, represent its address with a reg. */
DECL_RTL (decl) = gen_rtx_MEM (BLKmode, gen_reg_rtx (Pmode));
MEM_SET_IN_STRUCT_P (DECL_RTL (decl), AGGREGATE_TYPE_P (type));
set_mem_attributes (DECL_RTL (decl), decl, 1);
}
else if (DECL_MODE (decl) != BLKmode
/* If -ffloat-store, don't put explicit float vars
@ -3817,6 +3818,8 @@ expand_decl (decl)
mark_reg_pointer (DECL_RTL (decl),
TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
if (TREE_READONLY (decl))
RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
}
else if (TREE_CODE (DECL_SIZE_UNIT (decl)) == INTEGER_CST
@ -3841,8 +3844,6 @@ expand_decl (decl)
}
DECL_RTL (decl) = assign_temp (TREE_TYPE (decl), 1, 1, 1);
MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
AGGREGATE_TYPE_P (TREE_TYPE (decl)));
/* Set alignment we actually gave this decl. */
DECL_ALIGN (decl) = (DECL_MODE (decl) == BLKmode ? BIGGEST_ALIGNMENT
@ -3854,20 +3855,6 @@ expand_decl (decl)
if (addr != oldaddr)
emit_move_insn (oldaddr, addr);
}
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
AGGREGATE_TYPE_P (TREE_TYPE (decl)));
#if 0
/* If this is in memory because of -ffloat-store,
set the volatile bit, to prevent optimizations from
undoing the effects. */
if (flag_float_store && TREE_CODE (type) == REAL_TYPE)
MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
#endif
MEM_ALIAS_SET (DECL_RTL (decl)) = get_alias_set (decl);
}
else
/* Dynamic-size object: must push space on the stack. */
@ -3905,10 +3892,7 @@ expand_decl (decl)
/* Reference the variable indirect through that rtx. */
DECL_RTL (decl) = gen_rtx_MEM (DECL_MODE (decl), address);
/* If this is a memory ref that contains aggregate components,
mark it as such for cse and loop optimize. */
MEM_SET_IN_STRUCT_P (DECL_RTL (decl),
AGGREGATE_TYPE_P (TREE_TYPE (decl)));
set_mem_attributes (DECL_RTL (decl), decl, 1);
/* Indicate the alignment we actually gave this variable. */
#ifdef STACK_BOUNDARY
@ -3917,12 +3901,6 @@ expand_decl (decl)
DECL_ALIGN (decl) = BIGGEST_ALIGNMENT;
#endif
}
if (TREE_THIS_VOLATILE (decl))
MEM_VOLATILE_P (DECL_RTL (decl)) = 1;
if (TREE_READONLY (decl))
RTX_UNCHANGING_P (DECL_RTL (decl)) = 1;
}
/* Emit code to perform the initialization of a declaration DECL. */

View File

@ -1173,6 +1173,9 @@ finish_record_layout (rli)
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
/* Show any alias subsetting we need. */
record_component_aliases (rli->t);
/* Clean up. */
free (rli);
}

View File

@ -2090,13 +2090,13 @@ compile_file (name)
|| flag_test_coverage
|| warn_notreached);
init_regs ();
init_alias_once ();
init_decl_processing ();
init_optabs ();
init_stmt ();
init_eh ();
init_loop ();
init_reload ();
init_alias_once ();
init_function_once ();
init_stor_layout_once ();
init_varasm_once ();

View File

@ -246,10 +246,6 @@ static int next_decl_uid;
/* Unique id for next type created. */
static int next_type_uid = 1;
/* The language-specific function for alias analysis. If NULL, the
language does not do any special alias analysis. */
int (*lang_get_alias_set) PARAMS ((tree));
/* Here is how primitive or already-canonicalized types' hash
codes are made. */
#define TYPE_HASH(TYPE) ((unsigned long) (TYPE) & 0777777)
@ -5614,38 +5610,6 @@ tree_class_check_failed (node, cl, file, line, function)
#endif /* ENABLE_TREE_CHECKING */
/* Return the alias set for T, which may be either a type or an
expression. */
int
get_alias_set (t)
tree t;
{
/* If we're not doing any lanaguage-specific alias analysis, just
assume everything aliases everything else. */
if (! flag_strict_aliasing || lang_get_alias_set == 0)
return 0;
/* If this is a type with a known alias set, return it since this must
be the correct thing to do. */
else if (TYPE_P (t) && TYPE_ALIAS_SET_KNOWN_P (t))
return TYPE_ALIAS_SET (t);
else
return (*lang_get_alias_set) (t);
}
/* Return a brand-new alias set. */
int
new_alias_set ()
{
static int last_alias_set;
if (flag_strict_aliasing)
return ++last_alias_set;
else
return 0;
}
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT

View File

@ -1114,7 +1114,7 @@ struct tree_type
union tree_node *noncopied_parts;
union tree_node *context;
struct obstack *obstack;
int alias_set;
HOST_WIDE_INT alias_set;
/* Points to a structure whose details depend on the language in use. */
struct lang_type *lang_specific;
};
@ -1620,7 +1620,7 @@ struct tree_decl
} u2;
union tree_node *vindex;
int pointer_alias_set;
HOST_WIDE_INT pointer_alias_set;
/* Points to a structure whose details depend on the language in use. */
struct lang_decl *lang_specific;
};
@ -2373,9 +2373,6 @@ extern tree get_file_function_name_long PARAMS ((const char *));
extern tree get_set_constructor_bits PARAMS ((tree, char *, int));
extern tree get_set_constructor_bytes PARAMS ((tree,
unsigned char *, int));
extern int get_alias_set PARAMS ((tree));
extern int new_alias_set PARAMS ((void));
extern int (*lang_get_alias_set) PARAMS ((tree));
extern tree get_callee_fndecl PARAMS ((tree));
/* In stmt.c */