*** empty log message ***
From-SVN: r472
This commit is contained in:
parent
23b2ce5339
commit
d45cf215ee
@ -30,6 +30,10 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "tree.h"
|
||||
#include "c-tree.h"
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern char* xmalloc ();
|
||||
|
||||
enum formals_style_enum {
|
||||
@ -231,7 +235,7 @@ gen_formal_list_for_type (fntype, style)
|
||||
more typing information (for the parameter list) should be added (by
|
||||
hand) at some convenient moment.
|
||||
|
||||
The string chozen here is a comment with question marks in it. */
|
||||
The string chosen here is a comment with question marks in it. */
|
||||
|
||||
if (!*formal_list)
|
||||
{
|
||||
@ -636,7 +640,7 @@ gen_aux_info_record (fndecl, is_definition, is_implicit, is_prototyped)
|
||||
fprintf (aux_info_file, "/* compiled from: %s */\n", wd);
|
||||
}
|
||||
|
||||
/* Write the actual line of auxilliary info. */
|
||||
/* Write the actual line of auxiliary info. */
|
||||
|
||||
fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",
|
||||
DECL_SOURCE_FILE (fndecl),
|
||||
|
12
gcc/c-lex.c
12
gcc/c-lex.c
@ -1,4 +1,4 @@
|
||||
/* Lexical analyser for C and Objective C.
|
||||
/* Lexical analyzer for C and Objective C.
|
||||
Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -152,11 +152,11 @@ is_reserved_word (str, len)
|
||||
static struct resword wordlist[] =
|
||||
{
|
||||
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
|
||||
{"asm", ASM, NORID},
|
||||
{"asm", ASM_KEYWORD, NORID},
|
||||
{"",},
|
||||
{"__asm", ASM, NORID},
|
||||
{"__asm", ASM_KEYWORD, NORID},
|
||||
{"",},
|
||||
{"__asm__", ASM, NORID},
|
||||
{"__asm__", ASM_KEYWORD, NORID},
|
||||
{"break", BREAK, NORID},
|
||||
{"__typeof__", TYPEOF, NORID},
|
||||
{"",},
|
||||
@ -1084,7 +1084,7 @@ yylex ()
|
||||
|
||||
/* Even if we decided to recognize asm, still perhaps warn. */
|
||||
if (pedantic
|
||||
&& (value == ASM || value == TYPEOF
|
||||
&& (value == ASM_KEYWORD || value == TYPEOF
|
||||
|| ptr->rid == RID_INLINE)
|
||||
&& token_buffer[0] != '_')
|
||||
pedwarn ("ANSI does not permit the keyword `%s'",
|
||||
@ -1934,7 +1934,7 @@ done:
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Sets the value of the 'yydebug' varable to VALUE.
|
||||
/* Sets the value of the 'yydebug' variable to VALUE.
|
||||
This is a function so we don't have to have YYDEBUG defined
|
||||
in order to build the compiler. */
|
||||
|
||||
|
478
gcc/c-typeck.c
478
gcc/c-typeck.c
@ -47,6 +47,7 @@ static tree convert_sequence ();
|
||||
static tree unary_complex_lvalue ();
|
||||
static tree process_init_constructor ();
|
||||
static tree convert_arguments ();
|
||||
static char *get_spelling ();
|
||||
tree digest_init ();
|
||||
static void pedantic_lvalue_warning ();
|
||||
tree truthvalue_conversion ();
|
||||
@ -384,7 +385,7 @@ comptypes (type1, type2)
|
||||
if (TYPE_VOLATILE (t1) != TYPE_VOLATILE (t2))
|
||||
return 0;
|
||||
|
||||
/* If generating auxilliary info, allow for two different type nodes which
|
||||
/* If generating auxiliary info, allow for two different type nodes which
|
||||
have essentially the same definition. */
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
|
||||
@ -1101,7 +1102,7 @@ build_indirect_ref (ptr, errorstring)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* We *must* set TREE_READONLY when dereferencinga pointer to const,
|
||||
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
|
||||
so that we get the proper error message if the result is used
|
||||
to assign to. Also, &* is supposed to be a no-op.
|
||||
And ANSI C seems to specify that the type of the result
|
||||
@ -1943,7 +1944,8 @@ convert_arguments (typelist, values, name)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Optionally warn about conversions that can overflow. */
|
||||
/* Optionally warn about conversions that
|
||||
differ from the default conversions. */
|
||||
if (warn_conversion)
|
||||
{
|
||||
int formal_prec = TYPE_PRECISION (type);
|
||||
@ -1956,28 +1958,36 @@ convert_arguments (typelist, values, name)
|
||||
else if (TREE_CODE (type) == REAL_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (val)) != REAL_TYPE)
|
||||
warning ("integer argument converted to floating");
|
||||
else if (TREE_CODE (type) == REAL_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (val)) == REAL_TYPE)
|
||||
{
|
||||
/* Warn if any argument is passed as `float',
|
||||
since withtout a prototype it would be `double'. */
|
||||
if (formal_prec == TYPE_PRECISION (float_type_node))
|
||||
warning ("floating argument passed as `float' rather than `double'");
|
||||
}
|
||||
/* Detect integer changing in width or signedness. */
|
||||
else if ((TREE_CODE (type) == INTEGER_TYPE
|
||||
|| TREE_CODE (type) == ENUMERAL_TYPE)
|
||||
&& (TREE_CODE (TREE_TYPE (val)) == INTEGER_TYPE
|
||||
|| TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE)
|
||||
&& ((TREE_UNSIGNED (type)
|
||||
!= TREE_UNSIGNED (TREE_TYPE (val)))
|
||||
|| (MAX (formal_prec, int_prec)
|
||||
!= MAX (actual_prec, int_prec))))
|
||||
|| TREE_CODE (TREE_TYPE (val)) == ENUMERAL_TYPE))
|
||||
{
|
||||
if (MAX (formal_prec, int_prec)
|
||||
!= MAX (actual_prec, int_prec))
|
||||
warning ("integer argument converted in width");
|
||||
tree would_have_been = default_conversion (val);
|
||||
tree type1 = TREE_TYPE (would_have_been);
|
||||
|
||||
if (TYPE_PRECISION (type) != TYPE_PRECISION (type))
|
||||
warning ("prototype changes width used for integer argument");
|
||||
else if (TREE_UNSIGNED (type) == TREE_UNSIGNED (type1))
|
||||
;
|
||||
else if (TREE_CODE (val) == INTEGER_CST
|
||||
&& int_fits_type_p (val, type))
|
||||
/* Change in signedness doesn't matter
|
||||
if a constant value is unaffected. */
|
||||
;
|
||||
else if (TREE_UNSIGNED (type))
|
||||
warning ("signed argument converted to unsigned");
|
||||
warning ("argument passed as unsigned due to prototype");
|
||||
else
|
||||
warning ("unsigned argument converted to signed");
|
||||
warning ("argument passed as signed due to prototype");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2315,18 +2325,18 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|
||||
if (TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0))
|
||||
warning ("shift count exceeds width of value shifted");
|
||||
}
|
||||
/* Use the type of the value to be shifted.
|
||||
This is what most traditional C compilers do. */
|
||||
result_type = type0;
|
||||
/* Unless traditional, convert the shift-count to an integer,
|
||||
regardless of size of value being shifted. */
|
||||
if (! flag_traditional)
|
||||
{
|
||||
result_type = type0;
|
||||
if (TREE_TYPE (op1) != integer_type_node)
|
||||
op1 = convert (integer_type_node, op1);
|
||||
/* Avoid converting op1 to result_type later. */
|
||||
converted = 1;
|
||||
}
|
||||
else
|
||||
common = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2339,18 +2349,18 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|
||||
if (TREE_CODE (op1) == INTEGER_CST
|
||||
&& TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0))
|
||||
warning ("shift count exceeds width of value shifted");
|
||||
/* Use the type of the value to be shifted.
|
||||
This is what most traditional C compilers do. */
|
||||
result_type = type0;
|
||||
/* Unless traditional, convert the shift-count to an integer,
|
||||
regardless of size of value being shifted. */
|
||||
if (! flag_traditional)
|
||||
{
|
||||
result_type = type0;
|
||||
if (TREE_TYPE (op1) != integer_type_node)
|
||||
op1 = convert (integer_type_node, op1);
|
||||
/* Avoid converting op1 to result_type later. */
|
||||
converted = 1;
|
||||
}
|
||||
else
|
||||
common = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2364,18 +2374,18 @@ build_binary_op (code, orig_op0, orig_op1, convert_p)
|
||||
if (TREE_CODE (op1) == INTEGER_CST
|
||||
&& TREE_INT_CST_LOW (op1) >= TYPE_PRECISION (type0))
|
||||
warning ("shift count >= width of value shifted");
|
||||
/* Use the type of the value to be shifted.
|
||||
This is what most traditional C compilers do. */
|
||||
result_type = type0;
|
||||
/* Unless traditional, convert the shift-count to an integer,
|
||||
regardless of size of value being shifted. */
|
||||
if (! flag_traditional)
|
||||
{
|
||||
result_type = type0;
|
||||
if (TREE_TYPE (op1) != integer_type_node)
|
||||
op1 = convert (integer_type_node, op1);
|
||||
/* Avoid converting op1 to result_type later. */
|
||||
converted = 1;
|
||||
}
|
||||
else
|
||||
common = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2748,10 +2758,15 @@ pointer_int_sum (resultcode, ptrop, intop)
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE)
|
||||
{
|
||||
enum tree_code subcode = resultcode;
|
||||
tree int_type = TREE_TYPE (intop);
|
||||
if (TREE_CODE (intop) == MINUS_EXPR)
|
||||
subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
|
||||
ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1), 1);
|
||||
intop = TREE_OPERAND (intop, 0);
|
||||
/* Convert both subexpression types to the type of intop,
|
||||
because weird cases involving pointer arithmetic
|
||||
can result in a sum or difference with different type args. */
|
||||
ptrop = build_binary_op (subcode, ptrop,
|
||||
convert (int_type, TREE_OPERAND (intop, 1)), 1);
|
||||
intop = convert (int_type, TREE_OPERAND (intop, 0));
|
||||
}
|
||||
|
||||
/* Convert the integer argument to a type the same size as a pointer
|
||||
@ -3621,7 +3636,7 @@ build_c_cast (type, expr)
|
||||
value = default_conversion (value);
|
||||
otype = TREE_TYPE (value);
|
||||
|
||||
/* Optionally warn about potentially worrysome casts. */
|
||||
/* Optionally warn about potentially worrisome casts. */
|
||||
|
||||
if (warn_cast_qual
|
||||
&& TREE_CODE (type) == POINTER_TYPE
|
||||
@ -3636,15 +3651,13 @@ build_c_cast (type, expr)
|
||||
}
|
||||
|
||||
/* Warn about possible alignment problems. */
|
||||
#ifdef STRICT_ALIGNMENT
|
||||
if (warn_cast_align
|
||||
if (STRICT_ALIGNMENT && warn_cast_align
|
||||
&& TREE_CODE (type) == POINTER_TYPE
|
||||
&& TREE_CODE (otype) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (otype)) != VOID_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
|
||||
&& TYPE_ALIGN (TREE_TYPE (type)) > TYPE_ALIGN (TREE_TYPE (otype)))
|
||||
warning ("cast increases required alignment of target type");
|
||||
#endif
|
||||
|
||||
if (TREE_CODE (type) == INTEGER_TYPE
|
||||
&& TREE_CODE (otype) == POINTER_TYPE
|
||||
@ -3829,7 +3842,9 @@ build_modify_expr (lhs, modifycode, rhs)
|
||||
for assignments that are not allowed in C.
|
||||
ERRTYPE is a string to use in error messages:
|
||||
"assignment", "return", etc. If it is null, this is parameter passing
|
||||
for a function call (and different error messages are output).
|
||||
for a function call (and different error messages are output). Otherwise,
|
||||
it may be a name stored in the spelling stack and interpreted by
|
||||
get_spelling.
|
||||
|
||||
FUNNAME is the name of the function being called,
|
||||
as an IDENTIFIER_NODE, or null.
|
||||
@ -3900,7 +3915,7 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
&& !integer_zerop (rhs)
|
||||
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
|
||||
warn_for_assignment ("ANSI forbids %s between function pointer and `void *'",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
/* Const and volatile mean something different for function types,
|
||||
so the usual warnings are not appropriate. */
|
||||
else if (TREE_CODE (ttr) != FUNCTION_TYPE
|
||||
@ -3908,10 +3923,10 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
{
|
||||
if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))
|
||||
warn_for_assignment ("%s discards `const' from pointer target type",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))
|
||||
warn_for_assignment ("%s discards `volatile' from pointer target type",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3921,19 +3936,19 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
where an ordinary one is wanted, but not vice-versa. */
|
||||
if (TYPE_READONLY (ttl) && ! TYPE_READONLY (ttr))
|
||||
warn_for_assignment ("%s makes `const *' function pointer from non-const",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
if (TYPE_VOLATILE (ttl) && ! TYPE_VOLATILE (ttr))
|
||||
warn_for_assignment ("%s makes `volatile *' function pointer from non-volatile",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
}
|
||||
}
|
||||
else if (unsigned_type (TYPE_MAIN_VARIANT (ttl))
|
||||
== unsigned_type (TYPE_MAIN_VARIANT (ttr)))
|
||||
warn_for_assignment ("pointer targets in %s differ in signedness",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
else
|
||||
warn_for_assignment ("%s from incompatible pointer type",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
return convert (type, rhs);
|
||||
}
|
||||
else if (codel == POINTER_TYPE && coder == INTEGER_TYPE)
|
||||
@ -3941,7 +3956,7 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
if (! integer_zerop (rhs))
|
||||
{
|
||||
warn_for_assignment ("%s makes pointer from integer without a cast",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
return convert (type, rhs);
|
||||
}
|
||||
return null_pointer_node;
|
||||
@ -3949,7 +3964,7 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
|
||||
{
|
||||
warn_for_assignment ("%s makes integer from pointer without a cast",
|
||||
errtype, funname, parmnum);
|
||||
get_spelling (errtype), funname, parmnum);
|
||||
return convert (type, rhs);
|
||||
}
|
||||
|
||||
@ -3963,7 +3978,7 @@ convert_for_assignment (type, rhs, errtype, funname, parmnum)
|
||||
parmnum);
|
||||
}
|
||||
else
|
||||
error ("incompatible types in %s", errtype);
|
||||
error ("incompatible types in %s", get_spelling (errtype));
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
@ -4131,7 +4146,7 @@ store_init_value (decl, init)
|
||||
#if 0
|
||||
/* Note that this is the only place we can detect the error
|
||||
in a case such as struct foo bar = (struct foo) { x, y };
|
||||
where there is one initial value which is a constuctor expression. */
|
||||
where there is one initial value which is a constructor expression. */
|
||||
if (value == error_mark_node)
|
||||
;
|
||||
else if (TREE_STATIC (decl) && ! TREE_CONSTANT (value))
|
||||
@ -4160,18 +4175,190 @@ store_init_value (decl, init)
|
||||
DECL_INITIAL (decl) = value;
|
||||
}
|
||||
|
||||
/* Methods for storing and printing names for error messages.
|
||||
|
||||
/* Implement a spelling stack that allows components of a name to be pushed
|
||||
and popped. Each element on the stack is this structure. */
|
||||
|
||||
struct spelling
|
||||
{
|
||||
int kind;
|
||||
union
|
||||
{
|
||||
int i;
|
||||
char *s;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define SPELLING_STRING 1
|
||||
#define SPELLING_MEMBER 2
|
||||
#define SPELLING_BOUNDS 3
|
||||
|
||||
static struct spelling *spelling; /* Next stack element (unused). */
|
||||
static struct spelling *spelling_base; /* Spelling stack base. */
|
||||
static int spelling_size; /* Size of the spelling stack. */
|
||||
|
||||
/* Macros to save and restore the spelling stack around push_... functions.
|
||||
Alternative to SAVE_SPELLING_STACK. */
|
||||
|
||||
#define SPELLING_DEPTH() (spelling - spelling_base)
|
||||
#define RESTORE_SPELLING_DEPTH(depth) (spelling = spelling_base + depth)
|
||||
|
||||
/* Save and restore the spelling stack around arbitrary C code. */
|
||||
|
||||
#define SAVE_SPELLING_DEPTH(code) \
|
||||
{ \
|
||||
int __depth = SPELLING_DEPTH (); \
|
||||
code; \
|
||||
RESTORE_SPELLING_DEPTH (__depth); \
|
||||
}
|
||||
|
||||
/* Push an element on the spelling stack with type KIND and assign VALUE
|
||||
to MEMBER. */
|
||||
|
||||
#define PUSH_SPELLING(KIND, VALUE, MEMBER) \
|
||||
{ \
|
||||
int depth = SPELLING_DEPTH (); \
|
||||
\
|
||||
if (depth >= spelling_size) \
|
||||
{ \
|
||||
spelling_size += 10; \
|
||||
if (spelling_base == 0) \
|
||||
spelling_base \
|
||||
= (struct spelling *) xmalloc (spelling_size * sizeof (struct spelling)); \
|
||||
else \
|
||||
spelling_base \
|
||||
= (struct spelling *) xrealloc (spelling_base, \
|
||||
spelling_size * sizeof (struct spelling)); \
|
||||
RESTORE_SPELLING_DEPTH (depth); \
|
||||
} \
|
||||
\
|
||||
spelling->kind = (KIND); \
|
||||
spelling->MEMBER = (VALUE); \
|
||||
spelling++; \
|
||||
}
|
||||
|
||||
/* Push STRING on the stack. Printed literally. */
|
||||
|
||||
static void
|
||||
push_string (string)
|
||||
char *string;
|
||||
{
|
||||
PUSH_SPELLING (SPELLING_STRING, string, u.s);
|
||||
}
|
||||
|
||||
/* Push a member name on the stack. Printed as '.' STRING. */
|
||||
|
||||
static void
|
||||
push_member_name (string)
|
||||
char *string;
|
||||
{
|
||||
PUSH_SPELLING (SPELLING_MEMBER, string, u.s);
|
||||
}
|
||||
|
||||
/* Push an array bounds on the stack. Printed as [BOUNDS]. */
|
||||
|
||||
static void
|
||||
push_array_bounds (bounds)
|
||||
int bounds;
|
||||
{
|
||||
PUSH_SPELLING (SPELLING_BOUNDS, bounds, u.i);
|
||||
}
|
||||
|
||||
/* Compute the maximum size in bytes of the printed spelling. */
|
||||
|
||||
static int
|
||||
spelling_length ()
|
||||
{
|
||||
register int size = 0;
|
||||
register struct spelling *p;
|
||||
|
||||
for (p = spelling_base; p < spelling; p++)
|
||||
{
|
||||
if (p->kind == SPELLING_BOUNDS)
|
||||
size += 25;
|
||||
else
|
||||
size += strlen (p->u.s) + 1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Print the spelling to BUFFER and return it. */
|
||||
|
||||
static char *
|
||||
print_spelling (buffer)
|
||||
register char *buffer;
|
||||
{
|
||||
register char *d = buffer;
|
||||
register char *s;
|
||||
register struct spelling *p;
|
||||
|
||||
for (p = spelling_base; p < spelling; p++)
|
||||
if (p->kind == SPELLING_BOUNDS)
|
||||
{
|
||||
sprintf (d, "[%d]", p->u.i);
|
||||
d += strlen (d);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (p->kind == SPELLING_MEMBER)
|
||||
*d++ = '.';
|
||||
for (s = p->u.s; *d = *s++; d++)
|
||||
;
|
||||
}
|
||||
*d++ = '\0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Provide a means to pass component names derived from the spelling stack. */
|
||||
|
||||
char initialization_message;
|
||||
|
||||
/* Interpret the spelling of the given ERRTYPE message. */
|
||||
|
||||
static char *
|
||||
get_spelling (errtype)
|
||||
char *errtype;
|
||||
{
|
||||
static char *buffer;
|
||||
static int size = -1;
|
||||
|
||||
if (errtype == &initialization_message)
|
||||
{
|
||||
/* Avoid counting chars */
|
||||
static char message[] = "initialization of `%s'";
|
||||
register int needed = sizeof (message) + spelling_length () + 1;
|
||||
|
||||
if (size < 0)
|
||||
buffer = (char *) xmalloc (size = needed);
|
||||
if (needed > size)
|
||||
buffer = (char *) xrealloc (buffer, size = needed);
|
||||
|
||||
sprintf (buffer, message, print_spelling (alloca (needed)));
|
||||
return buffer;
|
||||
}
|
||||
|
||||
return errtype;
|
||||
}
|
||||
|
||||
/* Issue an error message for a bad initializer component.
|
||||
FORMAT describes the message. OFWHAT is the name for the component.
|
||||
LOCAL is a format string for formatting the insertion of the name
|
||||
into the message.
|
||||
|
||||
If OFWHAT is a null string, then LOCAL is omitted entirely. */
|
||||
If OFWHAT is null, the component name is stored on the spelling stack.
|
||||
If the compoment name is a null string, then LOCAL is omitted entirely. */
|
||||
|
||||
void
|
||||
error_init (format, local, ofwhat)
|
||||
char *format, *local, *ofwhat;
|
||||
{
|
||||
char *buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
|
||||
char *buffer;
|
||||
|
||||
if (ofwhat == 0)
|
||||
ofwhat = print_spelling (alloca (spelling_length () + 1));
|
||||
buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
|
||||
|
||||
if (*ofwhat)
|
||||
sprintf (buffer, local, ofwhat);
|
||||
@ -4186,13 +4373,18 @@ error_init (format, local, ofwhat)
|
||||
LOCAL is a format string for formatting the insertion of the name
|
||||
into the message.
|
||||
|
||||
If OFWHAT is a null string, then LOCAL is omitted entirely. */
|
||||
If OFWHAT is null, the component name is stored on the spelling stack.
|
||||
If the compoment name is a null string, then LOCAL is omitted entirely. */
|
||||
|
||||
void
|
||||
pedwarn_init (format, local, ofwhat)
|
||||
char *format, *local, *ofwhat;
|
||||
{
|
||||
char *buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
|
||||
char *buffer;
|
||||
|
||||
if (ofwhat == 0)
|
||||
ofwhat = print_spelling (alloca (spelling_length () + 1));
|
||||
buffer = (char *) alloca (strlen (local) + strlen (ofwhat) + 2);
|
||||
|
||||
if (*ofwhat)
|
||||
sprintf (buffer, local, ofwhat);
|
||||
@ -4215,8 +4407,9 @@ pedwarn_init (format, local, ofwhat)
|
||||
if non-constant initializers or elements are seen. CONSTRUCTOR_CONSTANT
|
||||
applies only to elements of constructors.
|
||||
|
||||
If OFWHAT is nonzero, it specifies what we are initializing, for error
|
||||
messages. Examples: variable name, variable.member, array[44]. */
|
||||
If OFWHAT is nonnull, it specifies what we are initializing, for error
|
||||
messages. Examples: variable name, variable.member, array[44].
|
||||
If OFWHAT is null, the component name is stored on the spelling stack. */
|
||||
|
||||
tree
|
||||
digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
|
||||
@ -4227,7 +4420,6 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
|
||||
enum tree_code code = TREE_CODE (type);
|
||||
tree element = 0;
|
||||
tree old_tail_contents;
|
||||
char *member_str; /* For building strings about member names. */
|
||||
/* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR
|
||||
tree node which has no TREE_TYPE. */
|
||||
int raw_constructor
|
||||
@ -4404,23 +4596,29 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Build the name of this member, with a "." for membership. */
|
||||
member_str = (char *) alloca (strlen (ofwhat)
|
||||
+ IDENTIFIER_LENGTH (DECL_NAME (field)) + 2);
|
||||
sprintf (member_str, "%s.%s", ofwhat,
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
SAVE_SPELLING_DEPTH
|
||||
({
|
||||
if (ofwhat)
|
||||
push_string (ofwhat);
|
||||
push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
|
||||
if (raw_constructor)
|
||||
return process_init_constructor (type, init, 0,
|
||||
require_constant,
|
||||
constructor_constant, member_str);
|
||||
else if (tail != 0)
|
||||
{
|
||||
*tail = old_tail_contents;
|
||||
return process_init_constructor (type, 0, tail,
|
||||
require_constant,
|
||||
constructor_constant, member_str);
|
||||
}
|
||||
if (raw_constructor)
|
||||
result = process_init_constructor (type, init, 0,
|
||||
require_constant,
|
||||
constructor_constant, 0);
|
||||
else if (tail != 0)
|
||||
{
|
||||
*tail = old_tail_contents;
|
||||
result = process_init_constructor (type, 0, tail,
|
||||
require_constant,
|
||||
constructor_constant, 0);
|
||||
}
|
||||
else
|
||||
result = 0;
|
||||
});
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle scalar types, including conversions. */
|
||||
@ -4449,16 +4647,13 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Build the name of the member being initialized, for error msgs. */
|
||||
{
|
||||
/* Avoid counting chars */
|
||||
static char message[] = "initialization of `%s'";
|
||||
member_str = (char *) alloca (strlen (ofwhat) + sizeof (message) + 1);
|
||||
sprintf (member_str, message, ofwhat);
|
||||
}
|
||||
|
||||
init = convert_for_assignment (type, default_conversion (init),
|
||||
member_str, NULL_TREE, 0);
|
||||
SAVE_SPELLING_DEPTH
|
||||
({
|
||||
if (ofwhat)
|
||||
push_string (ofwhat);
|
||||
init = convert_for_assignment (type, default_conversion (init),
|
||||
&initialization_message, NULL_TREE, 0);
|
||||
});
|
||||
|
||||
if (require_constant && ! TREE_CONSTANT (init))
|
||||
{
|
||||
@ -4533,7 +4728,8 @@ digest_init (type, init, tail, require_constant, constructor_constant, ofwhat)
|
||||
|
||||
OFWHAT is a character string describing the object being initialized,
|
||||
for error messages. It might be "variable" or "variable.member"
|
||||
or "variable[17].member[5]". */
|
||||
or "variable[17].member[5]". If OFWHAT is null, the description string
|
||||
is stored on the spelling stack. */
|
||||
|
||||
static tree
|
||||
process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
@ -4546,12 +4742,14 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
/* List of the elements of the result constructor,
|
||||
in reverse order. */
|
||||
register tree members = NULL;
|
||||
int members_length = 0;
|
||||
tree result;
|
||||
int allconstant = 1;
|
||||
int allsimple = 1;
|
||||
int erroneous = 0;
|
||||
char *member_str; /* String used to pass member names. */
|
||||
int depth = SPELLING_DEPTH ();
|
||||
|
||||
if (ofwhat)
|
||||
push_string (ofwhat);
|
||||
|
||||
/* Make TAIL be the list of elements to use for the initialization,
|
||||
no matter how the data was given to us. */
|
||||
@ -4567,21 +4765,34 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
tree domain = TYPE_DOMAIN (type);
|
||||
register long len;
|
||||
register int i;
|
||||
tree min_index, max_index, current_index, members_index;
|
||||
tree bound_type;
|
||||
tree one;
|
||||
|
||||
if (domain)
|
||||
len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain))
|
||||
- TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain))
|
||||
+ 1);
|
||||
/* If we have array bounds, set our bounds from that. Otherwise,
|
||||
we have a lower bound of zero and an unknown upper bound. Also
|
||||
set the type of the bounds; use "int" as default. */
|
||||
if (TYPE_DOMAIN (type))
|
||||
{
|
||||
min_index = members_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
|
||||
max_index = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
|
||||
bound_type = TREE_TYPE (min_index);
|
||||
}
|
||||
else
|
||||
len = -1; /* Take as many as there are */
|
||||
{
|
||||
min_index = members_index = integer_zero_node;
|
||||
max_index = 0;
|
||||
bound_type = integer_type_node;
|
||||
}
|
||||
|
||||
/* Don't leave the loop based on i if the next item has an explicit
|
||||
index value that will override i. */
|
||||
one = convert (bound_type, integer_one_node);
|
||||
|
||||
for (i = 0; tail != 0; i++)
|
||||
/* Don't leave the loop based on index if the next item has an explicit
|
||||
index value that will override it. */
|
||||
|
||||
for (current_index = min_index; tail != 0;
|
||||
current_index = fold (build (PLUS_EXPR, bound_type,
|
||||
current_index, one)))
|
||||
{
|
||||
register tree next1;
|
||||
|
||||
@ -4595,20 +4806,18 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
error ("field name used as index in array initializer");
|
||||
else if (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST)
|
||||
error ("non-constant array index in initializer");
|
||||
else if (domain != 0
|
||||
&& (tree_int_cst_lt (TREE_PURPOSE (tail),
|
||||
TYPE_MIN_VALUE (domain))
|
||||
|| tree_int_cst_lt (TYPE_MAX_VALUE (domain),
|
||||
TREE_PURPOSE (tail))))
|
||||
else if (tree_int_cst_lt (TREE_PURPOSE (tail), min_index)
|
||||
|| (max_index && tree_int_cst_lt (max_index,
|
||||
TREE_PURPOSE (tail))))
|
||||
error ("array index out of range in initializer");
|
||||
else
|
||||
i = TREE_INT_CST_LOW (TREE_PURPOSE (tail)), win = 1;
|
||||
current_index = TREE_PURPOSE (tail), win = 1;
|
||||
|
||||
if (!win)
|
||||
TREE_VALUE (tail) = error_mark_node;
|
||||
}
|
||||
|
||||
if (len >= 0 && i >= len)
|
||||
if (max_index && tree_int_cst_lt (max_index, current_index))
|
||||
break; /* Stop if we've indeed run out of elements. */
|
||||
|
||||
/* Now digest the value specified. */
|
||||
@ -4616,24 +4825,26 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
{
|
||||
tree tail1 = tail;
|
||||
|
||||
/* Build the index of this member, with a "." for membership. */
|
||||
member_str = (char *) alloca (25 + strlen (ofwhat));
|
||||
sprintf (member_str, "%s[%d]", ofwhat, i);
|
||||
|
||||
next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
/* Both of these are the same because
|
||||
a value here is an elt overall. */
|
||||
constant_element, constant_element,
|
||||
member_str);
|
||||
/* Build the element of this array, with "[]" notation. For
|
||||
error messages, we assume that the index fits within a
|
||||
host int. */
|
||||
SAVE_SPELLING_DEPTH
|
||||
({
|
||||
push_array_bounds (TREE_INT_CST_LOW (current_index));
|
||||
next1 = digest_init (TYPE_MAIN_VARIANT (TREE_TYPE (type)),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
/* Both of these are the same because
|
||||
a value here is an elt overall. */
|
||||
constant_element, constant_element, 0);
|
||||
});
|
||||
|
||||
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
|
||||
abort ();
|
||||
if (tail == tail1 && len < 0)
|
||||
if (tail == tail1 && TYPE_DOMAIN (type) == 0)
|
||||
{
|
||||
error_init (
|
||||
"non-empty initializer for array%s of empty elements",
|
||||
" `%s'", ofwhat);
|
||||
" `%s'", 0);
|
||||
/* Just ignore what we were supposed to use. */
|
||||
tail1 = 0;
|
||||
}
|
||||
@ -4654,17 +4865,22 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
|
||||
/* Now store NEXT1 in the list, I elements from the *end*.
|
||||
Make the list longer if necessary. */
|
||||
while (i >= members_length)
|
||||
while (! tree_int_cst_lt (current_index, members_index))
|
||||
{
|
||||
members = tree_cons (NULL_TREE, NULL_TREE, members);
|
||||
members_length++;
|
||||
members_index = fold (build (PLUS_EXPR, bound_type,
|
||||
members_index, one));
|
||||
}
|
||||
|
||||
{
|
||||
tree temp;
|
||||
int j;
|
||||
tree idx;
|
||||
|
||||
temp = members;
|
||||
for (j = members_length - 1; j > i; j--)
|
||||
for (idx = fold (build (MINUS_EXPR, bound_type,
|
||||
members_index, one));
|
||||
tree_int_cst_lt (current_index, idx);
|
||||
idx = fold (build (MINUS_EXPR, bound_type, idx, one)))
|
||||
temp = TREE_CHAIN (temp);
|
||||
TREE_VALUE (temp) = next1;
|
||||
}
|
||||
@ -4673,6 +4889,7 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
if (TREE_CODE (type) == RECORD_TYPE)
|
||||
{
|
||||
register tree field;
|
||||
int members_length = 0;
|
||||
int i;
|
||||
|
||||
/* Don't leave the loop based on field just yet; see if next item
|
||||
@ -4721,15 +4938,13 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
tree tail1 = tail;
|
||||
|
||||
/* Build the name of this member, with a "." for membership. */
|
||||
member_str = (char *) alloca (strlen (ofwhat)
|
||||
+ IDENTIFIER_LENGTH (DECL_NAME (field)) + 2);
|
||||
sprintf (member_str, "%s.%s", ofwhat,
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
|
||||
next1 = digest_init (TREE_TYPE (field),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
constant_element, constant_element,
|
||||
member_str);
|
||||
SAVE_SPELLING_DEPTH
|
||||
({
|
||||
push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
next1 = digest_init (TREE_TYPE (field),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
constant_element, constant_element, 0);
|
||||
});
|
||||
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
|
||||
abort ();
|
||||
tail = tail1;
|
||||
@ -4807,14 +5022,13 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
tree tail1 = tail;
|
||||
|
||||
/* Build the name of this member, with a "." for membership. */
|
||||
member_str = (char *) alloca (strlen (ofwhat)
|
||||
+ IDENTIFIER_LENGTH (DECL_NAME (field)) + 2);
|
||||
sprintf (member_str, "%s.%s", ofwhat,
|
||||
IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
|
||||
next1 = digest_init (TREE_TYPE (field),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
constant_value, constant_element, member_str);
|
||||
SAVE_SPELLING_DEPTH
|
||||
({
|
||||
push_member_name (IDENTIFIER_POINTER (DECL_NAME (field)));
|
||||
next1 = digest_init (TREE_TYPE (field),
|
||||
TREE_VALUE (tail), &tail1,
|
||||
constant_value, constant_element, 0);
|
||||
});
|
||||
if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST)
|
||||
abort ();
|
||||
tail = tail1;
|
||||
@ -4844,15 +5058,21 @@ process_init_constructor (type, init, elts, constant_value, constant_element,
|
||||
if (TREE_CODE (type) == UNION_TYPE)
|
||||
{
|
||||
pedwarn_init ("excess elements in union initializer%s",
|
||||
" after `%s'", ofwhat);
|
||||
" after `%s'", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
pedwarn_init ("excess elements in aggregate initializer%s",
|
||||
" after `%s'", ofwhat);
|
||||
" after `%s'", 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* It might be possible to use SAVE_SPELLING_DEPTH, but I suspect that
|
||||
some preprocessor somewhere won't accept that much text as an argument.
|
||||
It's also likely to make debugging difficult. */
|
||||
|
||||
RESTORE_SPELLING_DEPTH (depth);
|
||||
|
||||
if (erroneous)
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -508,7 +508,8 @@ expand_call (exp, target, ignore, modifier)
|
||||
mark_addressable (fndecl);
|
||||
}
|
||||
|
||||
if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl))
|
||||
if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl)
|
||||
&& TYPE_MODE (TREE_TYPE (exp)) != VOIDmode)
|
||||
is_const = 1;
|
||||
}
|
||||
}
|
||||
@ -717,7 +718,7 @@ expand_call (exp, target, ignore, modifier)
|
||||
If SETUP_INCOMING_VARARGS is defined, this machine will be able to
|
||||
place unnamed args that were passed in registers into the stack. So
|
||||
treat all args as named. This allows the insns emitting for a specific
|
||||
argument list to be independant of the function declaration.
|
||||
argument list to be independent of the function declaration.
|
||||
|
||||
If SETUP_INCOMING_VARARGS is not defined, we do not have any reliable
|
||||
way to pass unnamed args in registers, so we must force them into
|
||||
@ -1620,7 +1621,7 @@ target_for_arg (type, size, args_addr, offset)
|
||||
*ARG describes the argument value and where to pass it.
|
||||
|
||||
ARGBLOCK is the address of the stack-block for all the arguments,
|
||||
or 0 on a machine where arguemnts are pushed individually.
|
||||
or 0 on a machine where arguments are pushed individually.
|
||||
|
||||
MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
|
||||
so must be careful about how the stack is used.
|
||||
|
81
gcc/cse.c
81
gcc/cse.c
@ -96,7 +96,7 @@ Constants and quantity numbers
|
||||
in the appropriate element of qty_const. This is in addition to
|
||||
putting the constant in the hash table as is usual for non-regs.
|
||||
|
||||
Whether a reg or a constant is prefered is determined by the configuration
|
||||
Whether a reg or a constant is preferred is determined by the configuration
|
||||
macro CONST_COSTS and will often depend on the constant value. In any
|
||||
event, expressions containing constants can be simplified, by fold_rtx.
|
||||
|
||||
@ -323,7 +323,7 @@ static int cse_basic_block_start;
|
||||
static int cse_basic_block_end;
|
||||
|
||||
/* Vector mapping INSN_UIDs to cuids.
|
||||
The cuids are like uids but increase monononically always.
|
||||
The cuids are like uids but increase monotonically always.
|
||||
We use them to see whether a reg is used outside a given basic block. */
|
||||
|
||||
static short *uid_cuid;
|
||||
@ -2754,6 +2754,9 @@ simplify_unary_operation (code, mode, op, op_mode)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case SQRT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@ -2814,6 +2817,9 @@ simplify_unary_operation (code, mode, op, op_mode)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case SQRT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -2866,6 +2872,9 @@ simplify_unary_operation (code, mode, op, op_mode)
|
||||
d = (double) REAL_VALUE_UNSIGNED_FIX_TRUNCATE (d);
|
||||
break;
|
||||
|
||||
case SQRT:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
@ -5504,6 +5513,49 @@ cse_insn (insn, in_libcall_block)
|
||||
}
|
||||
}
|
||||
|
||||
/* Another possibility is that we have an AND with a constant in
|
||||
a mode narrower than a word. If so, it might have been generated
|
||||
as part of an "if" which would narrow the AND. If we already
|
||||
have done the AND in a wider mode, we can use a SUBREG of that
|
||||
value. */
|
||||
|
||||
if (flag_expensive_optimizations && ! src_related
|
||||
&& GET_CODE (src) == AND && GET_CODE (XEXP (src, 1)) == CONST_INT
|
||||
&& GET_MODE_SIZE (mode) < UNITS_PER_WORD)
|
||||
{
|
||||
enum machine_mode tmode;
|
||||
rtx new_and = gen_rtx (AND, VOIDmode, 0, XEXP (src, 1));
|
||||
|
||||
for (tmode = GET_MODE_WIDER_MODE (mode);
|
||||
GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
|
||||
tmode = GET_MODE_WIDER_MODE (tmode))
|
||||
{
|
||||
rtx inner = gen_lowpart_if_possible (tmode, XEXP (src, 0));
|
||||
struct table_elt *larger_elt;
|
||||
|
||||
if (inner)
|
||||
{
|
||||
PUT_MODE (new_and, tmode);
|
||||
XEXP (new_and, 0) = inner;
|
||||
larger_elt = lookup (new_and, HASH (new_and, tmode), tmode);
|
||||
if (larger_elt == 0)
|
||||
continue;
|
||||
|
||||
for (larger_elt = larger_elt->first_same_value;
|
||||
larger_elt; larger_elt = larger_elt->next_same_value)
|
||||
if (GET_CODE (larger_elt->exp) == REG)
|
||||
{
|
||||
src_related
|
||||
= gen_lowpart_if_possible (mode, larger_elt->exp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (src_related)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (src == src_folded)
|
||||
src_folded = 0;
|
||||
|
||||
@ -5734,7 +5786,7 @@ cse_insn (insn, in_libcall_block)
|
||||
/* If this is a single SET, we are setting a register, and we have an
|
||||
equivalent constant, we want to add a REG_NOTE. We don't want
|
||||
to write a REG_EQUAL note for a constant pseudo since verifying that
|
||||
that psuedo hasn't been eliminated is a pain. Such a note also
|
||||
that pseudo hasn't been eliminated is a pain. Such a note also
|
||||
won't help anything. */
|
||||
if (n_sets == 1 && src_const && GET_CODE (dest) == REG
|
||||
&& GET_CODE (src_const) != REG)
|
||||
@ -6761,7 +6813,7 @@ cse_end_of_basic_block (insn, data, follow_jumps, after_loop)
|
||||
/* If this is a conditional jump, we can follow it if -fcse-follow-jumps
|
||||
was specified, we haven't reached our maximum path length, there are
|
||||
insns following the target of the jump, this is the only use of the
|
||||
jump label, and the target label is preceeded by a BARRIER. */
|
||||
jump label, and the target label is preceded by a BARRIER. */
|
||||
else if (follow_jumps && path_size < PATHLENGTH - 1
|
||||
&& GET_CODE (p) == JUMP_INSN
|
||||
&& GET_CODE (PATTERN (p)) == SET
|
||||
@ -7115,7 +7167,7 @@ cse_basic_block (from, to, next_branch, around_loop)
|
||||
|
||||
/* See if it is ok to keep on going past the label
|
||||
which used to end our basic block. Remember that we incremented
|
||||
the count of that label, so we decremement it here. If we made
|
||||
the count of that label, so we decrement it here. If we made
|
||||
a jump unconditional, TO_USAGE will be one; in that case, we don't
|
||||
want to count the use in that jump. */
|
||||
|
||||
@ -7132,7 +7184,7 @@ cse_basic_block (from, to, next_branch, around_loop)
|
||||
/* Find the end of the following block. Note that we won't be
|
||||
following branches in this case. If TO was the last insn
|
||||
in the function, we are done. Similarly, if we deleted the
|
||||
insn after TO, it must have been because it was preceeded by
|
||||
insn after TO, it must have been because it was preceded by
|
||||
a BARRIER. In that case, we are done with this block because it
|
||||
has no continuation. */
|
||||
|
||||
@ -7266,6 +7318,7 @@ delete_dead_from_cse (insns, nreg)
|
||||
{
|
||||
int *counts = (int *) alloca (nreg * sizeof (int));
|
||||
rtx insn;
|
||||
rtx tem;
|
||||
int i;
|
||||
|
||||
/* First count the number of times each register is used. */
|
||||
@ -7287,6 +7340,14 @@ delete_dead_from_cse (insns, nreg)
|
||||
&& SET_DEST (PATTERN (insn)) == SET_SRC (PATTERN (insn)))
|
||||
;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0
|
||||
&& ! side_effects_p (SET_SRC (PATTERN (insn)))
|
||||
&& ((tem = next_nonnote_insn (insn)) == 0
|
||||
|| GET_RTX_CLASS (GET_CODE (tem)) != 'i'
|
||||
|| ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
|
||||
;
|
||||
#endif
|
||||
else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG
|
||||
|| REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
|
||||
|| counts[REGNO (SET_DEST (PATTERN (insn)))] != 0
|
||||
@ -7304,6 +7365,14 @@ delete_dead_from_cse (insns, nreg)
|
||||
&& SET_DEST (elt) == SET_SRC (elt))
|
||||
;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
else if (GET_CODE (SET_DEST (elt)) == CC0
|
||||
&& ! side_effects_p (SET_SRC (elt))
|
||||
&& ((tem = next_nonnote_insn (insn)) == 0
|
||||
|| GET_RTX_CLASS (GET_CODE (tem)) != 'i'
|
||||
|| ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
|
||||
;
|
||||
#endif
|
||||
else if (GET_CODE (SET_DEST (elt)) != REG
|
||||
|| REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER
|
||||
|| counts[REGNO (SET_DEST (elt))] != 0
|
||||
|
@ -25,7 +25,8 @@ enum debug_info_type
|
||||
NO_DEBUG, /* Write no debug info. */
|
||||
DBX_DEBUG, /* Write BSD .stabs for DBX (using dbxout.c). */
|
||||
SDB_DEBUG, /* Write COFF for (old) SDB (using sdbout.c). */
|
||||
DWARF_DEBUG /* Write Dwarf debug info (using dwarfout.c). */
|
||||
DWARF_DEBUG, /* Write Dwarf debug info (using dwarfout.c). */
|
||||
XCOFF_DEBUG /* Write IBM/Xcoff debug info (using dbxout.c). */
|
||||
};
|
||||
|
||||
/* Specify which kind of debugging info to generate. */
|
||||
@ -42,7 +43,7 @@ enum debug_info_level
|
||||
/* Specify how much debugging info to generate. */
|
||||
extern enum debug_info_level debug_info_level;
|
||||
|
||||
#ifdef DBX_DEBUGGING_INFO
|
||||
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
|
||||
/* Nonzero means use GDB-only extensions of DBX format. */
|
||||
extern int use_gdb_dbx_extensions;
|
||||
#endif
|
||||
@ -242,7 +243,7 @@ extern int flag_no_inline;
|
||||
|
||||
extern int flag_syntax_only;
|
||||
|
||||
/* Nonzero means we should save auxilliary info into a .X file. */
|
||||
/* Nonzero means we should save auxiliary info into a .X file. */
|
||||
|
||||
extern int flag_gen_aux_info;
|
||||
|
||||
|
@ -586,7 +586,7 @@ attr_string (str, len)
|
||||
/* Search the table for the string. */
|
||||
for (h = attr_hash_table[hashcode % RTL_HASH_SIZE]; h; h = h->next)
|
||||
if (h->hashcode == -hashcode
|
||||
&& !strcmp (h->u.str, str))
|
||||
&& !strncmp (h->u.str, str, len))
|
||||
return h->u.str; /* <-- return if found. */
|
||||
|
||||
/* Not found; create a permanent copy and add it to the hash table. */
|
||||
@ -2191,7 +2191,7 @@ simplify_test_exp (exp, insn_code, insn_index)
|
||||
|
||||
/* If either side is an IOR and we have (eq_attr "alternative" ..")
|
||||
present on both sides, apply the distributive law since this will
|
||||
yield simplications. */
|
||||
yield simplifications. */
|
||||
if ((GET_CODE (left) == IOR || GET_CODE (right) == IOR)
|
||||
&& compute_alternative_mask (left, IOR)
|
||||
&& compute_alternative_mask (right, IOR))
|
||||
|
@ -542,7 +542,7 @@ global_alloc (file)
|
||||
for the sake of debugging information. */
|
||||
if (n_basic_blocks > 0)
|
||||
#endif
|
||||
reload (basic_block_head[0], 1, file);
|
||||
reload (get_insns (), 1, file);
|
||||
}
|
||||
|
||||
/* Sort predicate for ordering the allocnos.
|
||||
@ -778,7 +778,7 @@ prune_preferences ()
|
||||
/* Scan least most important to most important.
|
||||
For each allocno, remove from preferences registers that cannot be used,
|
||||
either because of conflicts or register type. Then compute all registers
|
||||
prefered by each lower-priority register that conflicts. */
|
||||
preferred by each lower-priority register that conflicts. */
|
||||
|
||||
for (i = max_allocno - 1; i >= 0; i--)
|
||||
{
|
||||
@ -875,7 +875,7 @@ find_reg (allocno, losers, all_regs_p, accept_call_clobbered, retrying)
|
||||
IOR_HARD_REG_SET (used1, hard_reg_conflicts[allocno]);
|
||||
|
||||
/* Try each hard reg to see if it fits. Do this in two passes.
|
||||
In the first pass, skip registers that are prefered by some other pseudo
|
||||
In the first pass, skip registers that are preferred by some other pseudo
|
||||
to give it a better chance of getting one of those registers. Only if
|
||||
we can't get a register when excluding those do we take one of them.
|
||||
However, we never allocate a register for the first time in pass 0. */
|
||||
|
@ -508,6 +508,7 @@ save_for_inline_copying (fndecl)
|
||||
|
||||
case CODE_LABEL:
|
||||
copy = label_map[CODE_LABEL_NUMBER (insn)];
|
||||
LABEL_NAME (copy) = LABEL_NAME (insn);
|
||||
break;
|
||||
|
||||
case BARRIER:
|
||||
@ -2101,7 +2102,7 @@ try_constants (insn, map)
|
||||
|
||||
/* Substitute known constants for pseudo regs in the contents of LOC,
|
||||
which are part of INSN.
|
||||
If INSN is zero, the substition should always be done (this is used to
|
||||
If INSN is zero, the substitution should always be done (this is used to
|
||||
update DECL_RTL).
|
||||
These changes are taken out by try_constants if the result is not valid.
|
||||
|
||||
|
10
gcc/jump.c
10
gcc/jump.c
@ -640,7 +640,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we have an unconditional jump preceeded by a USE, try to put
|
||||
/* If we have an unconditional jump preceded by a USE, try to put
|
||||
the USE before the target and jump there. This simplifies many
|
||||
of the optimizations below since we don't have to worry about
|
||||
dealing with these USE insns. We only do this if the label
|
||||
@ -690,7 +690,7 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
|
||||
|
||||
We set:
|
||||
|
||||
TEMP to the jump insn preceeding "x = a;"
|
||||
TEMP to the jump insn preceding "x = a;"
|
||||
TEMP1 to X
|
||||
TEMP2 to the insn that sets "x = b;"
|
||||
TEMP3 to the insn that sets "x = a;" */
|
||||
@ -1418,11 +1418,13 @@ jump_optimize (f, cross_jump, noop_moves, after_regscan)
|
||||
|
||||
/* Include in each range any line number before it. */
|
||||
while (PREV_INSN (range1beg)
|
||||
&& GET_CODE (PREV_INSN (range1beg)) == NOTE)
|
||||
&& GET_CODE (PREV_INSN (range1beg)) == NOTE
|
||||
&& NOTE_LINE_NUMBER (PREV_INSN (range1beg)) > 0)
|
||||
range1beg = PREV_INSN (range1beg);
|
||||
|
||||
while (PREV_INSN (range2beg)
|
||||
&& GET_CODE (PREV_INSN (range2beg)) == NOTE)
|
||||
&& GET_CODE (PREV_INSN (range2beg)) == NOTE
|
||||
&& NOTE_LINE_NUMBER (PREV_INSN (range2beg)) > 0)
|
||||
range2beg = PREV_INSN (range2beg);
|
||||
|
||||
/* Don't move NOTEs for blocks or loops; shift them
|
||||
|
@ -368,7 +368,7 @@ local_alloc ()
|
||||
update_equiv_regs ();
|
||||
|
||||
/* This sets the maximum number of quantities we can have. Quantity
|
||||
numbers start at zero and we can have one for each psuedo plus the
|
||||
numbers start at zero and we can have one for each pseudo plus the
|
||||
number of SCRATCHs in the largest block, in the worst case. */
|
||||
max_qty = (max_regno - FIRST_PSEUDO_REGISTER) + max_scratch;
|
||||
|
||||
@ -640,7 +640,7 @@ memref_used_between_p (memref, start, end)
|
||||
register-register copy. */
|
||||
|
||||
static void
|
||||
optimize_reg_copy (insn, dest, src)
|
||||
optimize_reg_copy_1 (insn, dest, src)
|
||||
rtx insn;
|
||||
rtx dest;
|
||||
rtx src;
|
||||
@ -755,6 +755,85 @@ optimize_reg_copy (insn, dest, src)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* INSN is a copy of SRC to DEST, in which SRC dies. See if we now have
|
||||
a sequence of insns that modify DEST followed by an insn that sets
|
||||
SRC to DEST in which DEST dies, with no prior modification of DEST.
|
||||
(There is no need to check if the insns in between actually modify
|
||||
DEST. We should not have cases where DEST is not modified, but
|
||||
the optimization is safe if no such modification is detected.)
|
||||
In that case, we can replace all uses of DEST, starting with INSN and
|
||||
ending with the set of SRC to DEST, with SRC. We do not do this
|
||||
optimization if a CALL_INSN is crossed unless SRC already crosses a
|
||||
call.
|
||||
|
||||
It is assumed that DEST and SRC are pseudos; it is too complicated to do
|
||||
this for hard registers since the substitutions we may make might fail. */
|
||||
|
||||
static void
|
||||
optimize_reg_copy_2 (insn, dest, src)
|
||||
rtx insn;
|
||||
rtx dest;
|
||||
rtx src;
|
||||
{
|
||||
rtx p, q;
|
||||
rtx set;
|
||||
int sregno = REGNO (src);
|
||||
int dregno = REGNO (dest);
|
||||
|
||||
for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
|
||||
{
|
||||
if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
|
||||
|| (GET_CODE (p) == NOTE
|
||||
&& (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG
|
||||
|| NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)))
|
||||
break;
|
||||
|
||||
if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
|
||||
continue;
|
||||
|
||||
set = single_set (p);
|
||||
if (set && SET_SRC (set) == dest && SET_DEST (set) == src
|
||||
&& find_reg_note (p, REG_DEAD, dest))
|
||||
{
|
||||
/* We can do the optimization. Scan forward from INSN again,
|
||||
replacing regs as we go. */
|
||||
|
||||
/* Set to stop at next insn. */
|
||||
for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q))
|
||||
if (GET_RTX_CLASS (GET_CODE (q)) == 'i')
|
||||
{
|
||||
if (reg_mentioned_p (dest, PATTERN (q)))
|
||||
{
|
||||
PATTERN (q) = replace_rtx (PATTERN (q), dest, src);
|
||||
|
||||
/* We assume that a register is used exactly once per
|
||||
insn in the updates below. If this is not correct,
|
||||
no great harm is done. */
|
||||
reg_n_refs[sregno] -= loop_depth;
|
||||
reg_n_refs[dregno] += loop_depth;
|
||||
}
|
||||
|
||||
|
||||
if (GET_CODE (q) == CALL_INSN)
|
||||
{
|
||||
reg_n_calls_crossed[dregno]--;
|
||||
reg_n_calls_crossed[sregno]++;
|
||||
}
|
||||
}
|
||||
|
||||
remove_note (p, find_reg_note (p, REG_DEAD, dest));
|
||||
reg_n_deaths[dregno]--;
|
||||
remove_note (insn, find_reg_note (insn, REG_DEAD, src));
|
||||
reg_n_deaths[sregno]--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg_set_p (src, p)
|
||||
|| (GET_CODE (p) == CALL_INSN && reg_n_calls_crossed[sregno] == 0))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find registers that are equivalent to a single value throughout the
|
||||
compilation (either because they can be referenced in memory or are set once
|
||||
@ -825,7 +904,15 @@ update_equiv_regs ()
|
||||
if (flag_expensive_optimizations && GET_CODE (dest) == REG
|
||||
&& GET_CODE (SET_SRC (set)) == REG
|
||||
&& ! find_reg_note (insn, REG_DEAD, SET_SRC (set)))
|
||||
optimize_reg_copy (insn, dest, SET_SRC (set));
|
||||
optimize_reg_copy_1 (insn, dest, SET_SRC (set));
|
||||
|
||||
/* Similarly for a pseudo-pseudo copy when SRC is dead. */
|
||||
else if (flag_expensive_optimizations && GET_CODE (dest) == REG
|
||||
&& REGNO (dest) >= FIRST_PSEUDO_REGISTER
|
||||
&& GET_CODE (SET_SRC (set)) == REG
|
||||
&& REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
|
||||
&& find_reg_note (insn, REG_DEAD, SET_SRC (set)))
|
||||
optimize_reg_copy_2 (insn, dest, SET_SRC (set));
|
||||
|
||||
/* Otherwise, we only handle the case of a pseudo register being set
|
||||
once. */
|
||||
|
15
gcc/loop.c
15
gcc/loop.c
@ -48,7 +48,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "loop.h"
|
||||
|
||||
/* Vector mapping INSN_UIDs to luids.
|
||||
The luids are like uids but increase monononically always.
|
||||
The luids are like uids but increase monotonically always.
|
||||
We use them to see whether a jump comes from outside a given loop. */
|
||||
|
||||
int *uid_luid;
|
||||
@ -603,8 +603,7 @@ scan_loop (loop_start, end, nregs)
|
||||
}
|
||||
|
||||
/* Scan through the loop finding insns that are safe to move.
|
||||
In each such insn, store QImode as the mode, to mark it.
|
||||
Then set n_times_set negative for the reg being set, so that
|
||||
Set n_times_set negative for the reg being set, so that
|
||||
this reg will be considered invariant for subsequent insns.
|
||||
We consider whether subsequent insns use the reg
|
||||
in deciding whether it is worth actually moving.
|
||||
@ -3276,7 +3275,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
||||
else
|
||||
{
|
||||
/* Biv initial value is not simple move,
|
||||
so let it keep intial value of "itself". */
|
||||
so let it keep initial value of "itself". */
|
||||
|
||||
if (loop_dump_stream)
|
||||
fprintf (loop_dump_stream, "is complex\n");
|
||||
@ -3756,7 +3755,7 @@ strength_reduce (scan_start, end, loop_top, insn_count,
|
||||
This won't work if ! all_reduced,
|
||||
since the givs we planned to use might not have been reduced.
|
||||
|
||||
We have to be careful that we didn't initially think we could elminate
|
||||
We have to be careful that we didn't initially think we could eliminate
|
||||
this biv because of a giv that we now think may be dead and shouldn't
|
||||
be used as a biv replacement.
|
||||
|
||||
@ -3863,7 +3862,7 @@ valid_initial_value_p (x, insn, call_seen, loop_start)
|
||||
if (CONSTANT_P (x))
|
||||
return 1;
|
||||
|
||||
/* Only consider psuedos we know about initialized in insns whose luids
|
||||
/* Only consider pseudos we know about initialized in insns whose luids
|
||||
we know. */
|
||||
if (GET_CODE (x) != REG
|
||||
|| REGNO (x) >= max_reg_before_loop)
|
||||
@ -4106,7 +4105,7 @@ record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
|
||||
isn't computable if INSN insn't executed every iteration.
|
||||
However, for a DEST_ADDR giv, INSN merely uses the value of the giv;
|
||||
it does not compute a new value. Hence the value is always computable
|
||||
irregardless of whether INSN is executed each iteration. */
|
||||
regardless of whether INSN is executed each iteration. */
|
||||
|
||||
if (type == DEST_ADDR)
|
||||
v->always_computable = 1;
|
||||
@ -5818,7 +5817,7 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where)
|
||||
Insert insns to calculate new compare value. */
|
||||
|
||||
for (v = bl->giv; v; v = v->next_iv)
|
||||
if (CONSTANT_P (v->mult_val)
|
||||
if (CONSTANT_P (v->mult_val) && INTVAL (v->mult_val) > 0
|
||||
&& ! v->ignore && ! v->maybe_dead
|
||||
&& v->mode == mode)
|
||||
{
|
||||
|
43
gcc/optabs.c
43
gcc/optabs.c
@ -71,6 +71,7 @@ optab neg_optab;
|
||||
optab abs_optab;
|
||||
optab one_cmpl_optab;
|
||||
optab ffs_optab;
|
||||
optab sqrt_optab;
|
||||
|
||||
optab cmp_optab;
|
||||
optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
|
||||
@ -1183,7 +1184,7 @@ emit_unop_insn (icode, target, op0, code)
|
||||
/* Emit code to perform a series of operations on a multi-word quantity, one
|
||||
word at a time.
|
||||
|
||||
Such a block is preceeded by a CLOBBER of the output, consists of multiple
|
||||
Such a block is preceded by a CLOBBER of the output, consists of multiple
|
||||
insns, each setting one word of the output, and followed by a SET copying
|
||||
the output to itself.
|
||||
|
||||
@ -2829,6 +2830,7 @@ init_optabs ()
|
||||
abs_optab = init_optab (ABS);
|
||||
one_cmpl_optab = init_optab (NOT);
|
||||
ffs_optab = init_optab (FFS);
|
||||
sqrt_optab = init_optab (SQRT);
|
||||
|
||||
#ifdef HAVE_addqi3
|
||||
if (HAVE_addqi3)
|
||||
@ -3675,6 +3677,45 @@ init_optabs ()
|
||||
/* No library calls here! If there is no abs instruction,
|
||||
expand_expr will generate a conditional negation. */
|
||||
|
||||
#ifdef HAVE_sqrtqi2
|
||||
if (HAVE_sqrtqi2)
|
||||
sqrt_optab->handlers[(int) QImode].insn_code = CODE_FOR_sqrtqi2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrthi2
|
||||
if (HAVE_sqrthi2)
|
||||
sqrt_optab->handlers[(int) HImode].insn_code = CODE_FOR_sqrthi2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtpsi2
|
||||
if (HAVE_sqrtpsi2)
|
||||
sqrt_optab->handlers[(int) PSImode].insn_code = CODE_FOR_sqrtpsi2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtsi2
|
||||
if (HAVE_sqrtsi2)
|
||||
sqrt_optab->handlers[(int) SImode].insn_code = CODE_FOR_sqrtsi2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtdi2
|
||||
if (HAVE_sqrtdi2)
|
||||
sqrt_optab->handlers[(int) DImode].insn_code = CODE_FOR_sqrtdi2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtti2
|
||||
if (HAVE_sqrtti2)
|
||||
sqrt_optab->handlers[(int) TImode].insn_code = CODE_FOR_sqrtti2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtsf2
|
||||
if (HAVE_sqrtsf2)
|
||||
sqrt_optab->handlers[(int) SFmode].insn_code = CODE_FOR_sqrtsf2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrtdf2
|
||||
if (HAVE_sqrtdf2)
|
||||
sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
|
||||
#endif
|
||||
#ifdef HAVE_sqrttf2
|
||||
if (HAVE_sqrttf2)
|
||||
sqrt_optab->handlers[(int) TFmode].insn_code = CODE_FOR_sqrttf2;
|
||||
#endif
|
||||
/* No library calls here! If there is no sqrt instruction expand_builtin
|
||||
should force the library call. */
|
||||
|
||||
#ifdef HAVE_one_cmplqi2
|
||||
if (HAVE_one_cmplqi2)
|
||||
one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
|
||||
|
@ -1207,11 +1207,11 @@ abspath (cwd, rel_filename)
|
||||
/* Setup the current working directory as needed. */
|
||||
const char *cwd2 = (cwd) ? cwd : cwd_buffer;
|
||||
char *const abs_buffer
|
||||
= (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 1);
|
||||
= (char *) alloca (strlen (cwd2) + strlen (rel_filename) + 2);
|
||||
char *endp = abs_buffer;
|
||||
char *outp, *inp;
|
||||
|
||||
/* Copy the filename (possibly preceeded by the current working
|
||||
/* Copy the filename (possibly preceded by the current working
|
||||
directory name) into the absolutization buffer. */
|
||||
|
||||
{
|
||||
@ -1501,7 +1501,7 @@ referenced_file_is_newer (l, aux_info_mtime)
|
||||
a function definition or declaration.
|
||||
|
||||
Link this record onto the list of such records for the particular file in
|
||||
which it occured in proper (descending) line number order (for now).
|
||||
which it occurred in proper (descending) line number order (for now).
|
||||
|
||||
If there is an identical record already on the list for the file, throw
|
||||
this one away. Doing so takes care of the (useless and troublesome)
|
||||
@ -1678,7 +1678,7 @@ save_def_or_dec (l, is_syscalls)
|
||||
character of the name of the function that was declared/defined.
|
||||
If p points to another right paren, then this indicates that we
|
||||
are dealing with multiple formals lists. In that case, there
|
||||
really should be another right paren preceeding this right paren. */
|
||||
really should be another right paren preceding this right paren. */
|
||||
|
||||
if (*p != ')')
|
||||
break;
|
||||
@ -2580,7 +2580,7 @@ connect_defs_and_decs (hp)
|
||||
prototypes *should* all match exactly with one another and with the
|
||||
prototype for the actual function definition. We don't check for this
|
||||
here however, since we assume that the compiler must have already done
|
||||
this consistancy checking when it was creating the .X files. */
|
||||
this consistency checking when it was creating the .X files. */
|
||||
|
||||
for (dd_p = hp->ddip; dd_p; dd_p = dd_p->next_for_func)
|
||||
if (dd_p->prototyped)
|
||||
@ -3418,7 +3418,7 @@ add_local_decl (def_dec_p, clean_text_p)
|
||||
output_string (decl);
|
||||
}
|
||||
|
||||
/* Finally, write out a new indent string, just like the preceeding one
|
||||
/* Finally, write out a new indent string, just like the preceding one
|
||||
that we found. This will typically include a newline as the first
|
||||
character of the indent string. */
|
||||
|
||||
|
@ -241,10 +241,9 @@ static void change_stack ();
|
||||
static void convert_regs ();
|
||||
static void dump_stack_info ();
|
||||
|
||||
/* Return non-zero if any stack register is mentioned somewhere within
|
||||
PAT. */
|
||||
/* Return non-zero if any stack register is mentioned somewhere within PAT. */
|
||||
|
||||
static int
|
||||
int
|
||||
stack_regs_mentioned_p (pat)
|
||||
register rtx pat;
|
||||
{
|
||||
@ -1450,7 +1449,7 @@ stack_reg_life_analysis (first)
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
This section deals with stack register substition, and forms the second
|
||||
This section deals with stack register substitution, and forms the second
|
||||
pass over the RTL.
|
||||
*****************************************************************************/
|
||||
|
||||
@ -2623,7 +2622,7 @@ goto_block_pat (insn, regstack, pat)
|
||||
}
|
||||
|
||||
/* Traverse all basic blocks in a function, converting the register
|
||||
refereces in each insn from the "flat" register file that gcc uses, to
|
||||
references in each insn from the "flat" register file that gcc uses, to
|
||||
the stack-like registers the 387 uses. */
|
||||
|
||||
static void
|
||||
|
28
gcc/reload.c
28
gcc/reload.c
@ -284,6 +284,16 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
|
||||
enum machine_mode t_mode = VOIDmode;
|
||||
enum insn_code t_icode = CODE_FOR_nothing;
|
||||
|
||||
/* If X is a pseudo-register that has an equivalent MEM (actually, if it
|
||||
is still a pseudo-register by now, it *must* have an equivalent MEM
|
||||
but we don't want to assume that), use that equivalent when seeing if
|
||||
a secondary reload is needed since whether or not a reload is needed
|
||||
might be sensitive to the form of the MEM. */
|
||||
|
||||
if (GET_CODE (x) == REG && REGNO (x) >= FIRST_PSEUDO_REGISTER
|
||||
&& reg_equiv_mem[REGNO (x)] != 0)
|
||||
x = reg_equiv_mem[REGNO (x)];
|
||||
|
||||
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|
||||
if (in_p)
|
||||
class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x);
|
||||
@ -323,8 +333,10 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
|
||||
in operand 1. Outputs should have an initial "=", which we must
|
||||
skip. */
|
||||
|
||||
char insn_letter = insn_operand_constraint[(int) icode][!in_p][in_p];
|
||||
enum reg_class insn_class
|
||||
= REG_CLASS_FROM_LETTER (insn_operand_constraint[(int) icode][!in_p][in_p]);
|
||||
= (insn_letter == 'r' ? GENERAL_REGS
|
||||
: REG_CLASS_FROM_LETTER (insn_letter));
|
||||
|
||||
if (insn_class == NO_REGS
|
||||
|| (in_p && insn_operand_constraint[(int) icode][!in_p][0] != '=')
|
||||
@ -337,10 +349,11 @@ find_secondary_reload (x, reload_class, reload_mode, in_p, picode, pmode,
|
||||
mode = insn_operand_mode[(int) icode][2];
|
||||
else
|
||||
{
|
||||
char t_letter = insn_operand_constraint[(int) icode][2][2];
|
||||
class = insn_class;
|
||||
t_mode = insn_operand_mode[(int) icode][2];
|
||||
t_class
|
||||
= REG_CLASS_FROM_LETTER (insn_operand_constraint[(int) icode][2][2]);
|
||||
t_class = (t_letter == 'r' ? GENERAL_REGS
|
||||
: REG_CLASS_FROM_LETTER (t_letter));
|
||||
t_icode = icode;
|
||||
icode = CODE_FOR_nothing;
|
||||
}
|
||||
@ -1831,7 +1844,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
||||
bcopy (constraints, constraints1, noperands * sizeof (char *));
|
||||
n_alternatives = n_occurrences (',', constraints[0]) + 1;
|
||||
for (i = 1; i < noperands; i++)
|
||||
if (n_alternatives != n_occurrences (',', constraints[0]) + 1)
|
||||
if (n_alternatives != n_occurrences (',', constraints[i]) + 1)
|
||||
{
|
||||
error_for_asm (insn, "operand constraints differ in number of alternatives");
|
||||
/* Avoid further trouble with this insn. */
|
||||
@ -2012,6 +2025,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
|
||||
&XEXP (recog_operand[i], 0),
|
||||
recog_operand[i], ind_levels);
|
||||
substed_operand[i] = recog_operand[i] = *recog_operand_loc[i];
|
||||
|
||||
/* This is no longer a psuedo register. To prevent later code
|
||||
from thinking it still is, we must reset the preferred_class
|
||||
to NO_REGS. */
|
||||
preferred_class[i] = NO_REGS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3403,7 +3421,7 @@ find_reloads_address (mode, memrefloc, ad, loc, operand, ind_levels)
|
||||
is that it is itself a MEM. This can happen when the frame pointer is
|
||||
being eliminated, a pseudo is not allocated to a hard register, and the
|
||||
offset between the frame and stack pointers is not its initial value.
|
||||
In that case the psuedo will have been replaced by a MEM referring to
|
||||
In that case the pseudo will have been replaced by a MEM referring to
|
||||
the stack pointer. */
|
||||
if (GET_CODE (ad) == MEM)
|
||||
{
|
||||
|
@ -236,7 +236,7 @@ int reload_in_progress = 0;
|
||||
enum insn_code reload_in_optab[NUM_MACHINE_MODES];
|
||||
enum insn_code reload_out_optab[NUM_MACHINE_MODES];
|
||||
|
||||
/* This obstack is used for allocation of rtl during register elmination.
|
||||
/* This obstack is used for allocation of rtl during register elimination.
|
||||
The allocated storage can be freed once find_reloads has processed the
|
||||
insn. */
|
||||
|
||||
@ -744,7 +744,7 @@ reload (first, global, dumpfile)
|
||||
/* This loop scans the entire function each go-round
|
||||
and repeats until one repetition spills no additional hard regs. */
|
||||
|
||||
/* This flag is set when a psuedo reg is spilled,
|
||||
/* This flag is set when a pseudo reg is spilled,
|
||||
to require another pass. Note that getting an additional reload
|
||||
reg does not necessarily imply any pseudo reg was spilled;
|
||||
sometimes we find a reload reg that no pseudo reg was allocated in. */
|
||||
@ -880,7 +880,7 @@ reload (first, global, dumpfile)
|
||||
}
|
||||
}
|
||||
|
||||
/* If we allocated another psuedo to the stack, redo elimination
|
||||
/* If we allocated another pseudo to the stack, redo elimination
|
||||
bookkeeping. */
|
||||
if (something_changed)
|
||||
continue;
|
||||
@ -1188,7 +1188,7 @@ reload (first, global, dumpfile)
|
||||
of that class should be quite rare.
|
||||
|
||||
If a group is needed, the size and mode of the group will
|
||||
have been set up at the begining of this loop. */
|
||||
have been set up at the beginning of this loop. */
|
||||
|
||||
if (GET_CODE (insn) == CALL_INSN
|
||||
&& caller_save_spill_class != NO_REGS)
|
||||
@ -2171,7 +2171,7 @@ set_label_offsets (x, insn, initial_p)
|
||||
}
|
||||
|
||||
/* Otherwise, if this is the definition of a label and it is
|
||||
preceeded by a BARRIER, set our offsets to the known offset of
|
||||
preceded by a BARRIER, set our offsets to the known offset of
|
||||
that label. */
|
||||
|
||||
else if (x == insn
|
||||
@ -2579,7 +2579,7 @@ eliminate_regs (x, mem_mode, insn)
|
||||
|
||||
case CLOBBER:
|
||||
/* If clobbering a register that is the replacement register for an
|
||||
elimination we still think can be peformed, note that it cannot
|
||||
elimination we still think can be performed, note that it cannot
|
||||
be performed. Otherwise, we need not be concerned about it. */
|
||||
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
|
||||
if (ep->to_rtx == XEXP (x, 0))
|
||||
@ -4324,8 +4324,8 @@ choose_reload_regs (insn, avoid_return_reg)
|
||||
{
|
||||
int s = reload_order[i];
|
||||
|
||||
if ((reload_in[s] == 0 && reload_out[s] == 0 &&
|
||||
! reload_secondary_p[s])
|
||||
if ((reload_in[s] == 0 && reload_out[s] == 0
|
||||
&& ! reload_secondary_p[s])
|
||||
|| reload_optional[s])
|
||||
continue;
|
||||
|
||||
@ -4479,7 +4479,7 @@ emit_reload_insns (insn)
|
||||
/* Values to be put in spill_reg_store are put here first. */
|
||||
rtx new_spill_reg_store[FIRST_PSEUDO_REGISTER];
|
||||
|
||||
/* If this is a CALL_INSN preceeded by USE insns, any reload insns
|
||||
/* If this is a CALL_INSN preceded by USE insns, any reload insns
|
||||
must go in front of the first USE insn, not in front of INSN. */
|
||||
|
||||
if (GET_CODE (insn) == CALL_INSN && GET_CODE (PREV_INSN (insn)) == INSN
|
||||
@ -5637,9 +5637,9 @@ inc_for_reload (reloadreg, value, inc_amount, insn)
|
||||
{
|
||||
/* If incrementing a register, assume we can
|
||||
output an insn to increment it directly. */
|
||||
if (GET_CODE (incloc) == REG &&
|
||||
(REGNO (incloc) < FIRST_PSEUDO_REGISTER
|
||||
|| reg_renumber[REGNO (incloc)] >= 0))
|
||||
if (GET_CODE (incloc) == REG
|
||||
&& (REGNO (incloc) < FIRST_PSEUDO_REGISTER
|
||||
|| reg_renumber[REGNO (incloc)] >= 0))
|
||||
{
|
||||
rtx first_new
|
||||
= emit_insn_before (gen_add2_insn (incloc,
|
||||
@ -5676,9 +5676,9 @@ inc_for_reload (reloadreg, value, inc_amount, insn)
|
||||
|
||||
/* If incrementing a register, assume we can
|
||||
output an insn to increment it directly. */
|
||||
if (GET_CODE (incloc) == REG &&
|
||||
(REGNO (incloc) < FIRST_PSEUDO_REGISTER
|
||||
|| reg_renumber[REGNO (incloc)] >= 0))
|
||||
if (GET_CODE (incloc) == REG
|
||||
&& (REGNO (incloc) < FIRST_PSEUDO_REGISTER
|
||||
|| reg_renumber[REGNO (incloc)] >= 0))
|
||||
{
|
||||
emit_insn_before (gen_add2_insn (incloc,
|
||||
gen_rtx (CONST_INT, VOIDmode,
|
||||
|
@ -95,7 +95,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
On machines that use CC0, we are very conservative. We will not make
|
||||
a copy of an insn involving CC0 since we want to maintain a 1-1
|
||||
correspondance between the insn that sets and uses CC0. The insns are
|
||||
correspondence between the insn that sets and uses CC0. The insns are
|
||||
allowed to be separated by placing an insn that sets CC0 (but not an insn
|
||||
that uses CC0; we could do this, but it doesn't seem worthwhile) in a
|
||||
delay slot. In that case, we point each insn at the other with REG_CC_USER
|
||||
@ -2666,7 +2666,7 @@ fill_slots_from_thread (insn, condition, thread, opposite_thread, likely,
|
||||
update THREAD and NEW_THREAD if it is done in the loop below. Also
|
||||
initialize NEW_THREAD. */
|
||||
|
||||
new_thread = thread = try_split (PATTERN (thread), thread);
|
||||
new_thread = thread = try_split (PATTERN (thread), thread, 0);
|
||||
|
||||
/* Scan insns at THREAD. We are looking for an insn that can be removed
|
||||
from THREAD (it neither sets nor references resources that were set
|
||||
|
@ -108,7 +108,7 @@ typedef struct rtx_def
|
||||
1 in a LABEL_REF if this is a reference to a label outside the
|
||||
current loop.
|
||||
1 in an INSN, JUMP_INSN, or CALL_INSN if this insn must be scheduled
|
||||
together with the preceeding insn. Valid only within sched.
|
||||
together with the preceding insn. Valid only within sched.
|
||||
1 in an INSN, JUMP_INSN, or CALL_INSN if insn is in a delay slot and
|
||||
from the target of a branch. Valid from reorg until end of compilation;
|
||||
cleared before used. */
|
||||
@ -271,7 +271,7 @@ typedef struct rtvec_def{
|
||||
REG_LABEL points to a CODE_LABEL. Used by non-JUMP_INSNs to
|
||||
say that the CODE_LABEL contained in the REG_LABEL note is used
|
||||
by the insn.
|
||||
REG_DEP_ANTI is used in LOG_LINKS which represent anti (write after read)
|
||||
REG_DEP_ANTI is used in LOG_LINKS which represent anti (write after read)
|
||||
dependencies. REG_DEP_OUTPUT is used in LOG_LINKS which represent output
|
||||
(write after write) dependencies. Data dependencies, which are the only
|
||||
type of LOG_LINK created by flow, are represented by a 0 reg note kind. */
|
||||
@ -433,7 +433,7 @@ extern char *note_insn_name[];
|
||||
#define REG_LOOP_TEST_P(RTX) ((RTX)->in_struct)
|
||||
|
||||
/* During sched, for an insn, 1 means that the insn must be scheduled together
|
||||
with the preceeding insn. */
|
||||
with the preceding insn. */
|
||||
#define SCHED_GROUP_P(INSN) ((INSN)->in_struct)
|
||||
|
||||
/* For a SET rtx, SET_DEST is the place that is set
|
||||
|
Loading…
x
Reference in New Issue
Block a user