*** empty log message ***

From-SVN: r472
This commit is contained in:
Richard Stallman 1992-03-14 05:07:15 +00:00
parent 23b2ce5339
commit d45cf215ee
19 changed files with 649 additions and 207 deletions

View File

@ -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),

View File

@ -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. */

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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))

View File

@ -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. */

View File

@ -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.

View File

@ -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

View File

@ -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. */

View File

@ -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)
{

View File

@ -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;

View File

@ -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. */

View File

@ -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

View File

@ -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)
{

View File

@ -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 < &reg_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,

View File

@ -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

View File

@ -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