FreeBSD uses stock versions of these GCC files.

This commit is contained in:
Alexander Kabaev 2003-07-11 04:00:23 +00:00
parent eb05e163fc
commit b2bcf6753d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=117404
21 changed files with 14736 additions and 8165 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -34,16 +34,32 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
lang_identifier nodes, because some keywords are only special in a
particular context. */
struct lang_identifier
struct lang_identifier GTY(())
{
struct c_common_identifier ignore;
tree global_value, local_value, label_value, implicit_decl;
tree error_locus, limbo_value;
struct c_common_identifier common_id;
tree global_value;
tree local_value;
tree label_value;
tree implicit_decl;
tree error_locus;
tree limbo_value;
};
/* The resulting tree type. */
union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
generic;
struct lang_identifier GTY ((tag ("1"))) identifier;
};
/* Language-specific declaration information. */
struct lang_decl
struct lang_decl GTY(())
{
struct c_lang_decl base;
/* The return types and parameter types may have variable size.
@ -107,10 +123,10 @@ struct lang_decl
(DECL_LANG_SPECIFIC (NODE)->base.declared_inline)
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type
struct lang_type GTY(())
{
int len;
tree elts[1];
tree GTY((length ("%h.len"))) elts[1];
};
/* Record whether a type or decl was written with nonconstant size.
@ -150,29 +166,36 @@ struct lang_type
/* in c-lang.c and objc-act.c */
extern tree lookup_interface PARAMS ((tree));
extern tree is_class_name PARAMS ((tree));
extern void maybe_objc_check_decl PARAMS ((tree));
extern tree objc_is_id PARAMS ((tree));
extern void objc_check_decl PARAMS ((tree));
extern void finish_file PARAMS ((void));
extern int maybe_objc_comptypes PARAMS ((tree, tree, int));
extern tree maybe_building_objc_message_expr PARAMS ((void));
extern int recognize_objc_keyword PARAMS ((void));
extern int objc_comptypes PARAMS ((tree, tree, int));
extern tree objc_message_selector PARAMS ((void));
extern tree lookup_objc_ivar PARAMS ((tree));
/* in c-parse.in */
extern void c_parse_init PARAMS ((void));
extern void c_set_yydebug PARAMS ((int));
extern int yyparse_1 PARAMS ((void));
/* in c-aux-info.c */
extern void gen_aux_info_record PARAMS ((tree, int, int, int));
/* in c-decl.c */
extern int global_bindings_p PARAMS ((void));
extern int kept_level_p PARAMS ((void));
extern tree getdecls PARAMS ((void));
extern void pushlevel PARAMS ((int));
extern tree poplevel PARAMS ((int,int, int));
extern void insert_block PARAMS ((tree));
extern void set_block PARAMS ((tree));
extern tree pushdecl PARAMS ((tree));
extern void c_insert_default_attributes PARAMS ((tree));
extern void c_init_decl_processing PARAMS ((void));
extern void c_dup_lang_specific_decl PARAMS ((tree));
extern void c_print_identifier PARAMS ((FILE *, tree, int));
extern tree build_array_declarator PARAMS ((tree, tree, int, int));
extern tree build_enumerator PARAMS ((tree, tree));
extern int c_decode_option PARAMS ((int, char **));
extern void c_mark_varargs PARAMS ((void));
extern void check_for_loop_decls PARAMS ((void));
extern void clear_parm_order PARAMS ((void));
extern int complete_array_type PARAMS ((tree, tree, int));
@ -191,14 +214,12 @@ extern tree implicitly_declare PARAMS ((tree));
extern void implicit_decl_warning PARAMS ((tree));
extern int in_parm_level_p PARAMS ((void));
extern void keep_next_level PARAMS ((void));
extern int kept_level_p PARAMS ((void));
extern tree lookup_name PARAMS ((tree));
extern tree lookup_name_current_level PARAMS ((tree));
extern void parmlist_tags_warning PARAMS ((void));
extern void pending_xref_error PARAMS ((void));
extern void mark_c_function_context PARAMS ((struct function *));
extern void push_c_function_context PARAMS ((struct function *));
extern void pop_c_function_context PARAMS ((struct function *));
extern void c_push_function_context PARAMS ((struct function *));
extern void c_pop_function_context PARAMS ((struct function *));
extern void pop_label_level PARAMS ((void));
extern void push_label_level PARAMS ((void));
extern void push_parm_decl PARAMS ((tree));
@ -218,7 +239,7 @@ extern tree xref_tag PARAMS ((enum tree_code, tree));
extern tree c_begin_compound_stmt PARAMS ((void));
extern void c_expand_deferred_function PARAMS ((tree));
extern void c_expand_decl_stmt PARAMS ((tree));
extern tree make_pointer_declarator PARAMS ((tree, tree));
/* in c-objc-common.c */
extern int c_disregard_inline_limits PARAMS ((tree));
@ -227,23 +248,28 @@ extern const char *c_objc_common_init PARAMS ((const char *));
extern int c_missing_noreturn_ok_p PARAMS ((tree));
extern void c_objc_common_finish_file PARAMS ((void));
extern int defer_fn PARAMS ((tree));
extern bool c_warn_unused_global_decl PARAMS ((tree));
#define c_build_type_variant(TYPE, CONST_P, VOLATILE_P) \
c_build_qualified_type ((TYPE), \
((CONST_P) ? TYPE_QUAL_CONST : 0) | \
((VOLATILE_P) ? TYPE_QUAL_VOLATILE : 0))
#define c_sizeof_nowarn(T) c_sizeof_or_alignof_type (T, SIZEOF_EXPR, 0)
/* in c-typeck.c */
extern tree require_complete_type PARAMS ((tree));
extern int comptypes PARAMS ((tree, tree));
extern tree c_sizeof_nowarn PARAMS ((tree));
extern tree c_size_in_bytes PARAMS ((tree));
extern bool c_mark_addressable PARAMS ((tree));
extern void c_incomplete_type_error PARAMS ((tree, tree));
extern tree c_type_promotes_to PARAMS ((tree));
extern tree build_component_ref PARAMS ((tree, tree));
extern tree build_indirect_ref PARAMS ((tree, const char *));
extern tree build_array_ref PARAMS ((tree, tree));
extern tree build_external_ref PARAMS ((tree, int));
extern tree parser_build_binary_op PARAMS ((enum tree_code,
tree, tree));
extern int c_tree_expr_nonnegative_p PARAMS ((tree));
extern void readonly_warning PARAMS ((tree, const char *));
extern tree build_conditional_expr PARAMS ((tree, tree, tree));
extern tree build_compound_expr PARAMS ((tree));
@ -287,94 +313,14 @@ extern int current_function_returns_null;
extern int current_function_returns_abnormally;
/* Nonzero means `$' can be in an identifier. */
extern int dollars_in_ident;
/* Nonzero means allow type mismatches in conditional expressions;
just make their values `void'. */
extern int flag_cond_mismatch;
/* Nonzero means don't recognize the keyword `asm'. */
extern int flag_no_asm;
/* Nonzero means warn about implicit declarations. */
extern int warn_implicit;
/* Nonzero means warn for all old-style non-prototype function decls. */
extern int warn_strict_prototypes;
/* Nonzero means warn about multiple (redundant) decls for the same single
variable or function. */
extern int warn_redundant_decls;
/* Nonzero means warn about extern declarations of objects not at
file-scope level and about *all* declarations of functions (whether
extern or static) not at file-scope level. Note that we exclude
implicit function declarations. To get warnings about those, use
-Wimplicit. */
extern int warn_nested_externs;
/* Nonzero means warn about pointer casts that can drop a type qualifier
from the pointer target type. */
extern int warn_cast_qual;
/* Nonzero means warn when casting a function call to a type that does
not match the return type (e.g. (float)sqrt() or (anything*)malloc()
when there is no previous declaration of sqrt or malloc. */
extern int warn_bad_function_cast;
/* Warn about traditional constructs whose meanings changed in ANSI C. */
extern int warn_traditional;
/* Warn about a subscript that has type char. */
extern int warn_char_subscripts;
/* Warn if main is suspicious. */
extern int warn_main;
/* Nonzero means to allow single precision math even if we're generally
being traditional. */
extern int flag_allow_single_precision;
/* Warn if initializer is not completely bracketed. */
extern int warn_missing_braces;
/* Warn about comparison of signed and unsigned values. */
extern int warn_sign_compare;
/* Warn about testing equality of floating point numbers. */
extern int warn_float_equal;
/* Warn about multicharacter constants. */
extern int warn_multichar;
/* Nonzero means we are reading code that came from a system header file. */
extern int system_header_p;
/* Warn about implicit declarations. 1 = warning, 2 = error. */
extern int mesg_implicit_function_declaration;
/* In c-decl.c */
extern void finish_incomplete_decl PARAMS ((tree));
extern void c_finish_incomplete_decl PARAMS ((tree));
extern tree static_ctors;
extern tree static_dtors;
extern GTY(()) tree static_ctors;
extern GTY(()) tree static_dtors;
#endif /* ! GCC_C_TREE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Definitions for Sun Sparc64 running FreeBSD using the ELF format
/* Definitions for Sun SPARC64 running FreeBSD using the ELF format
Copyright (C) 2001, 2002 Free Software Foundation, Inc.
Contributed by David E. O'Brien <obrien@FreeBSD.org> and BSDi.
@ -29,7 +29,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Because we include sparc/sysv4.h. */
#undef CPP_PREDEFINES
#define CPP_PREDEFINES FBSD_CPP_PREDEFINES
/* Do not define it here, we now use TARGET_OS_CPP_BUILTINS. */
#define LINK_SPEC "%(link_arch) \
%{!mno-relax:%{!r:-relax}} \
@ -55,14 +55,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
We use the GCC defaults instead. */
#undef WCHAR_TYPE
#undef WCHAR_UNSIGNED
#define WCHAR_UNSIGNED 0
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
/* Define for support of TFmode long double and REAL_ARITHMETIC.
Sparc ABI says that long double is 4 words. */
/* Define for support of TFmode long double.
SPARC ABI says that long double is 4 words. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)

4201
contrib/gcc/configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -31,10 +31,10 @@ Boston, MA 02111-1307, USA. */
#include "libfuncs.h"
#include "cp-tree.h"
#include "flags.h"
#include "obstack.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "tree-inline.h"
static void push_eh_cleanup PARAMS ((tree));
static tree prepare_eh_type PARAMS ((tree));
@ -46,15 +46,14 @@ static void push_eh_cleanup PARAMS ((tree));
static bool decl_is_java_type PARAMS ((tree decl, int err));
static void initialize_handler_parm PARAMS ((tree, tree));
static tree do_allocate_exception PARAMS ((tree));
static tree stabilize_throw_expr PARAMS ((tree, tree *));
static tree wrap_cleanups_r PARAMS ((tree *, int *, void *));
static int complete_ptr_ref_or_void_ptr_p PARAMS ((tree, tree));
static bool is_admissible_throw_operand PARAMS ((tree));
static int can_convert_eh PARAMS ((tree, tree));
static void check_handlers_1 PARAMS ((tree, tree));
static tree cp_protect_cleanup_actions PARAMS ((void));
#include "decl.h"
#include "obstack.h"
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@ -118,7 +117,7 @@ prepare_eh_type (type)
}
/* Build the address of a typeinfo decl for use in the runtime
matching field of the exception model. */
matching field of the exception model. */
static tree
build_eh_type_type (type)
@ -175,17 +174,13 @@ static int
dtor_nothrow (type)
tree type;
{
tree fn;
if (type == NULL_TREE)
return 0;
if (! TYPE_HAS_DESTRUCTOR (type))
return 1;
fn = lookup_member (type, dtor_identifier, 0, 0);
fn = TREE_VALUE (fn);
return TREE_NOTHROW (fn);
return TREE_NOTHROW (CLASSTYPE_DESTRUCTORS (type));
}
/* Build up a call to __cxa_end_catch, to destroy the exception object
@ -518,7 +513,7 @@ do_allocate_exception (type)
#if 0
/* Call __cxa_free_exception from a cleanup. This is never invoked
directly. */
directly, but see the comment for stabilize_throw_expr. */
static tree
do_free_exception (ptr)
@ -540,6 +535,92 @@ do_free_exception (ptr)
}
#endif
/* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR.
Called from build_throw via walk_tree_without_duplicates. */
static tree
wrap_cleanups_r (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
tree exp = *tp;
tree cleanup;
/* Don't walk into types. */
if (TYPE_P (exp))
{
*walk_subtrees = 0;
return NULL_TREE;
}
if (TREE_CODE (exp) != TARGET_EXPR)
return NULL_TREE;
cleanup = TARGET_EXPR_CLEANUP (exp);
if (cleanup)
{
cleanup = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (cleanup), cleanup);
TARGET_EXPR_CLEANUP (exp) = cleanup;
}
/* Keep iterating. */
return NULL_TREE;
}
/* Like stabilize_expr, but specifically for a thrown expression. When
throwing a temporary class object, we want to construct it directly into
the thrown exception, so we look past the TARGET_EXPR and stabilize the
arguments of the call instead.
The case where EXP is a call to a function returning a class is a bit of
a grey area in the standard; it's unclear whether or not it should be
allowed to throw. I'm going to say no, as that allows us to optimize
this case without worrying about deallocating the exception object if it
does. The alternatives would be either not optimizing this case, or
wrapping the initialization in a TRY_CATCH_EXPR to call do_free_exception
rather than in a MUST_NOT_THROW_EXPR, for this case only. */
static tree
stabilize_throw_expr (exp, initp)
tree exp;
tree *initp;
{
tree init_expr;
if (TREE_CODE (exp) == TARGET_EXPR
&& TREE_CODE (TARGET_EXPR_INITIAL (exp)) == AGGR_INIT_EXPR
&& flag_elide_constructors)
{
tree aggr_init = AGGR_INIT_EXPR_CHECK (TARGET_EXPR_INITIAL (exp));
tree args = TREE_OPERAND (aggr_init, 1);
tree newargs = NULL_TREE;
tree *p = &newargs;
init_expr = void_zero_node;
for (; args; args = TREE_CHAIN (args))
{
tree arg = TREE_VALUE (args);
tree arg_init_expr;
arg = stabilize_expr (arg, &arg_init_expr);
if (TREE_SIDE_EFFECTS (arg_init_expr))
init_expr = build (COMPOUND_EXPR, void_type_node, init_expr,
arg_init_expr);
*p = tree_cons (NULL_TREE, arg, NULL_TREE);
p = &TREE_CHAIN (*p);
}
TREE_OPERAND (aggr_init, 1) = newargs;
}
else
{
exp = stabilize_expr (exp, &init_expr);
}
*initp = init_expr;
return exp;
}
/* Build a throw expression. */
tree
@ -585,10 +666,9 @@ build_throw (exp)
{
tree throw_type;
tree cleanup;
tree stmt_expr;
tree compound_stmt;
tree object, ptr;
tree tmp;
tree temp_expr, allocate_expr;
fn = get_identifier ("__cxa_throw");
if (IDENTIFIER_GLOBAL_VALUE (fn))
@ -614,8 +694,6 @@ build_throw (exp)
fn = push_throw_library_fn (fn, tmp);
}
begin_init_stmts (&stmt_expr, &compound_stmt);
/* throw expression */
/* First, decay it. */
exp = decay_conversion (exp);
@ -633,37 +711,40 @@ build_throw (exp)
the call to __cxa_allocate_exception first (which doesn't
matter, since it can't throw). */
my_friendly_assert (stmts_are_full_exprs_p () == 1, 19990926);
/* Store the throw expression into a temp. This can be less
efficient than storing it into the allocated space directly, but
if we allocated the space first we would have to deal with
cleaning it up if evaluating this expression throws. */
if (TREE_SIDE_EFFECTS (exp))
{
tmp = create_temporary_var (TREE_TYPE (exp));
DECL_INITIAL (tmp) = exp;
cp_finish_decl (tmp, exp, NULL_TREE, LOOKUP_ONLYCONVERTING);
exp = tmp;
}
/* Pre-evaluate the thrown expression first, since if we allocated
the space first we would have to deal with cleaning it up if
evaluating this expression throws. */
exp = stabilize_throw_expr (exp, &temp_expr);
/* Allocate the space for the exception. */
ptr = create_temporary_var (ptr_type_node);
DECL_REGISTER (ptr) = 1;
cp_finish_decl (ptr, NULL_TREE, NULL_TREE, LOOKUP_ONLYCONVERTING);
tmp = do_allocate_exception (TREE_TYPE (exp));
tmp = build_modify_expr (ptr, INIT_EXPR, tmp);
finish_expr_stmt (tmp);
allocate_expr = do_allocate_exception (TREE_TYPE (exp));
allocate_expr = get_target_expr (allocate_expr);
ptr = TARGET_EXPR_SLOT (allocate_expr);
object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
object = build_indirect_ref (object, NULL);
exp = build_modify_expr (object, INIT_EXPR, exp);
/* And initialize the exception object. */
exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
if (exp == error_mark_node)
error (" in thrown expression");
{
error (" in thrown expression");
return error_mark_node;
}
exp = build1 (MUST_NOT_THROW_EXPR, TREE_TYPE (exp), exp);
finish_expr_stmt (exp);
/* Prepend the allocation. */
exp = build (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp);
if (temp_expr != void_zero_node)
{
/* Prepend the calculation of the throw expression. Also, force
any cleanups from the expression to be evaluated here so that
we don't have to do them during unwinding. But first wrap
them in MUST_NOT_THROW_EXPR, since they are run after the
exception object is initialized. */
walk_tree_without_duplicates (&temp_expr, wrap_cleanups_r, 0);
exp = build (COMPOUND_EXPR, TREE_TYPE (exp), temp_expr, exp);
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
}
throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object)));
@ -671,9 +752,9 @@ build_throw (exp)
{
cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
complete_dtor_identifier, 0);
cleanup = TREE_VALUE (cleanup);
cleanup = BASELINK_FUNCTIONS (cleanup);
mark_used (cleanup);
mark_addressable (cleanup);
cxx_mark_addressable (cleanup);
/* Pretend it's a normal function. */
cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
}
@ -686,13 +767,11 @@ build_throw (exp)
tmp = tree_cons (NULL_TREE, cleanup, NULL_TREE);
tmp = tree_cons (NULL_TREE, throw_type, tmp);
tmp = tree_cons (NULL_TREE, ptr, tmp);
/* ??? Indicate that this function call throws throw_type. */
tmp = build_function_call (fn, tmp);
/* ??? Indicate that this function call throws throw_type. */
finish_expr_stmt (tmp);
exp = finish_init_stmts (stmt_expr, compound_stmt);
/* Tack on the initialization stuff. */
exp = build (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp);
}
else
{
@ -708,6 +787,8 @@ build_throw (exp)
(fn, build_function_type (void_type_node, void_list_node));
}
/* ??? Indicate that this function call allows exceptions of the type
of the enclosing catch block (if known). */
exp = build_function_call (fn, NULL_TREE);
}
@ -718,7 +799,7 @@ build_throw (exp)
/* Make sure TYPE is complete, pointer to complete, reference to
complete, or pointer to cv void. Issue diagnostic on failure.
Return the zero on failure and non-zero on success. FROM can be
Return the zero on failure and nonzero on success. FROM can be
the expr or decl from whence TYPE came, if available. */
static int

View File

@ -1,6 +1,6 @@
/* Output dbx-format symbol table information from GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
@ -155,7 +155,7 @@ static int source_label_number = 1;
#endif
#ifdef DEBUG_SYMS_TEXT
#define FORCE_TEXT text_section ();
#define FORCE_TEXT function_section (current_function_decl);
#else
#define FORCE_TEXT
#endif
@ -309,6 +309,7 @@ static void print_int_cst_octal PARAMS ((tree));
static void print_octal PARAMS ((unsigned HOST_WIDE_INT, int));
static void print_wide_int PARAMS ((HOST_WIDE_INT));
static void dbxout_type_name PARAMS ((tree));
static void dbxout_class_name_qualifiers PARAMS ((tree));
static int dbxout_symbol_location PARAMS ((tree, tree, const char *, rtx));
static void dbxout_symbol_name PARAMS ((tree, const char *, int));
static void dbxout_prepare_symbol PARAMS ((tree));
@ -327,7 +328,7 @@ static void dbxout_begin_block PARAMS ((unsigned, unsigned));
static void dbxout_end_block PARAMS ((unsigned, unsigned));
static void dbxout_function_decl PARAMS ((tree));
struct gcc_debug_hooks dbx_debug_hooks =
const struct gcc_debug_hooks dbx_debug_hooks =
{
dbxout_init,
dbxout_finish,
@ -340,8 +341,8 @@ struct gcc_debug_hooks dbx_debug_hooks =
debug_true_tree, /* ignore_block */
dbxout_source_line, /* source_line */
dbxout_source_line, /* begin_prologue: just output line info */
debug_nothing_int, /* end_prologue */
debug_nothing_void, /* end_epilogue */
debug_nothing_int_charstar, /* end_prologue */
debug_nothing_int_charstar, /* end_epilogue */
#ifdef DBX_FUNCTION_FIRST
dbxout_begin_function,
#else
@ -357,7 +358,7 @@ struct gcc_debug_hooks dbx_debug_hooks =
#endif /* DBX_DEBUGGING_INFO */
#if defined (XCOFF_DEBUGGING_INFO)
struct gcc_debug_hooks xcoff_debug_hooks =
const struct gcc_debug_hooks xcoff_debug_hooks =
{
dbxout_init,
dbxout_finish,
@ -370,7 +371,7 @@ struct gcc_debug_hooks xcoff_debug_hooks =
debug_true_tree, /* ignore_block */
xcoffout_source_line,
xcoffout_begin_prologue, /* begin_prologue */
debug_nothing_int, /* end_prologue */
debug_nothing_int_charstar, /* end_prologue */
xcoffout_end_epilogue,
debug_nothing_tree, /* begin_function */
xcoffout_end_function,
@ -417,7 +418,7 @@ dbxout_init (input_file_name)
const char *input_file_name;
{
char ltext_label_name[100];
tree syms = getdecls ();
tree syms = (*lang_hooks.decls.getdecls) ();
asmfile = asm_out_file;
@ -674,7 +675,7 @@ dbxout_global_decl (decl)
&& ! DECL_EXTERNAL (decl)
&& DECL_RTL_SET_P (decl)) /* Not necessary? */
dbxout_symbol (decl, 0);
}
}
/* At the end of compilation, finish writing the symbol table.
Unless you define DBX_OUTPUT_MAIN_SOURCE_FILE_END, the default is
@ -1019,7 +1020,7 @@ dbxout_type_methods (type)
}
if (!need_prefix)
{
putc (';', asmfile);
putc (';', asmfile);
CHARS (1);
}
}
@ -1107,7 +1108,9 @@ dbxout_type (type, full)
static int anonymous_type_number = 0;
if (TREE_CODE (type) == VECTOR_TYPE)
type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
/* The frontend feeds us a representation for the vector as a struct
containing an array. Pull out the array type. */
type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
/* If there was an input error and we don't really have a type,
avoid crashing and write something that is at least valid
@ -1279,7 +1282,7 @@ dbxout_type (type, full)
write it as a subtype. */
else if (TREE_TYPE (type) != 0
&& TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE)
{
{
/* If the size is non-standard, say what it is if we can use
GDB extensions. */
@ -1292,10 +1295,10 @@ dbxout_type (type, full)
}
dbxout_range_type (type);
}
}
else
{
{
/* If the size is non-standard, say what it is if we can use
GDB extensions. */
@ -1319,7 +1322,7 @@ dbxout_type (type, full)
larger. This is because we print the bounds as signed decimal,
and hence they can't span same size unsigned types. */
if (use_gnu_debug_info_extensions
if (use_gnu_debug_info_extensions
&& TYPE_MIN_VALUE (type) != 0
&& TREE_CODE (TYPE_MIN_VALUE (type)) == INTEGER_CST
&& TYPE_MAX_VALUE (type) != 0
@ -1348,7 +1351,7 @@ dbxout_type (type, full)
else
/* Output other integer types as subranges of `int'. */
dbxout_range_type (type);
}
}
break;
@ -1861,7 +1864,7 @@ print_wide_int (c)
CHARS (digs);
}
/* Output the name of type TYPE, with no punctuation.
Such names can be set up either by typedef declarations
or by struct, enum and union tags. */
@ -1887,6 +1890,33 @@ dbxout_type_name (type)
fprintf (asmfile, "%s", IDENTIFIER_POINTER (t));
CHARS (IDENTIFIER_LENGTH (t));
}
/* Output leading leading struct or class names needed for qualifying
type whose scope is limited to a struct or class. */
static void
dbxout_class_name_qualifiers (decl)
tree decl;
{
tree context = decl_type_context (decl);
if (context != NULL_TREE
&& TREE_CODE(context) == RECORD_TYPE
&& TYPE_NAME (context) != 0
&& (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
|| (DECL_NAME (TYPE_NAME (context)) != 0)))
{
tree name = TYPE_NAME (context);
if (TREE_CODE (name) == TYPE_DECL)
{
dbxout_class_name_qualifiers (name);
name = DECL_NAME (name);
}
fprintf (asmfile, "%s::", IDENTIFIER_POINTER (name));
CHARS (IDENTIFIER_LENGTH (name) + 2);
}
}
/* Output a .stabs for the symbol defined by DECL,
which must be a ..._DECL node in the normal namespace.
@ -2007,7 +2037,7 @@ dbxout_symbol (decl, local)
&& !TREE_ASM_WRITTEN (TYPE_NAME (type))
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
&& DECL_ARTIFICIAL (decl)
&& DECL_ARTIFICIAL (decl)
/* Do not generate a tag for records of variable size,
since this type can not be properly described in the
DBX format, and it confuses some tools such as objdump. */
@ -2028,9 +2058,17 @@ dbxout_symbol (decl, local)
dbxout_finish_symbol (NULL_TREE);
}
/* Output .stabs (or whatever) and leading double quote. */
fprintf (asmfile, "%s\"", ASM_STABS_OP);
if (use_gnu_debug_info_extensions)
{
/* Output leading class/struct qualifiers. */
dbxout_class_name_qualifiers (decl);
}
/* Output typedef name. */
fprintf (asmfile, "%s\"%s:", ASM_STABS_OP,
IDENTIFIER_POINTER (DECL_NAME (decl)));
fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (decl)));
/* Short cut way to output a tag also. */
if ((TREE_CODE (type) == RECORD_TYPE
@ -2039,7 +2077,7 @@ dbxout_symbol (decl, local)
&& TYPE_NAME (type) == decl
/* Distinguish the implicit typedefs of C++
from explicit ones that might be found in C. */
&& DECL_ARTIFICIAL (decl))
&& DECL_ARTIFICIAL (decl))
{
if (use_gnu_debug_info_extensions && have_used_extensions)
{
@ -2172,7 +2210,7 @@ dbxout_symbol (decl, local)
result = dbxout_symbol_location (decl, type, 0, DECL_RTL (decl));
break;
default:
break;
}
@ -2196,7 +2234,7 @@ dbxout_symbol_location (decl, type, suffix, home)
/* Don't mention a variable at all
if it was completely optimized into nothingness.
If the decl was from an inline function, then its rtl
is not identically the rtl that was used in this
particular compilation. */
@ -2275,7 +2313,7 @@ dbxout_symbol_location (decl, type, suffix, home)
|| GET_CODE (tmp) == LABEL_REF)
current_sym_addr = tmp;
}
/* Ultrix `as' seems to need this. */
#ifdef DBX_STATIC_STAB_DATA_SECTION
data_section ();
@ -2480,7 +2518,7 @@ dbxout_finish_symbol (sym)
#endif
}
/* Output definitions of all the decls in a chain. Return non-zero if
/* Output definitions of all the decls in a chain. Return nonzero if
anything was output */
int
@ -2564,7 +2602,7 @@ dbxout_parms (parms)
}
/* It is quite tempting to use:
dbxout_type (TREE_TYPE (parms), 0);
as the next statement, rather than using DECL_ARG_TYPE(), so
@ -2577,7 +2615,7 @@ dbxout_parms (parms)
double on the stack, but if we emit a stab saying the type is a
float, then gdb will only read in a single value, and this will
produce an erroneous value. */
dbxout_type (DECL_ARG_TYPE (parms), 0);
dbxout_type (DECL_ARG_TYPE (parms), 0);
current_sym_value = DEBUGGER_ARG_OFFSET (current_sym_value, addr);
dbxout_finish_symbol (parms);
}
@ -2695,13 +2733,14 @@ dbxout_parms (parms)
const char *const decl_name = (DECL_NAME (parms)
? IDENTIFIER_POINTER (DECL_NAME (parms))
: "(anon)");
if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
current_sym_value = 0;
if (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 0)) == REG)
current_sym_value = 0;
else
current_sym_value
= INTVAL (XEXP (XEXP (XEXP (DECL_RTL (parms), 0), 0), 1));
current_sym_addr = 0;
current_sym_code = N_PSYM;
FORCE_TEXT;
fprintf (asmfile, "%s\"%s:v", ASM_STABS_OP, decl_name);
@ -2739,7 +2778,7 @@ dbxout_parms (parms)
&& TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
&& GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
{
current_sym_value +=
current_sym_value +=
GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms)));
}
@ -2849,7 +2888,7 @@ dbxout_block (block, depth, args)
int blocknum = -1;
#if DBX_BLOCKS_FUNCTION_RELATIVE
const char *begin_label;
const char *begin_label;
if (current_function_func_begin_label != NULL_TREE)
begin_label = IDENTIFIER_POINTER (current_function_func_begin_label);
else

View File

@ -1,6 +1,6 @@
/* Output Dwarf format symbol table information from the GNU C compiler.
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998,
1999, 2000, 2001 Free Software Foundation, Inc.
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 2002,
1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
This file is part of GCC.
@ -43,7 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
The generation of DWARF debugging information by the GNU version 2.x C
compiler has now been tested rather extensively for m88k, i386, i860, and
Sparc targets. The DWARF output of the GNU C compiler appears to inter-
SPARC targets. The DWARF output of the GNU C compiler appears to inter-
operate well with the standard SVR4 SDB debugger on these kinds of target
systems (but of course, there are no guarantees).
@ -162,7 +162,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
is required by the current DWARF draft specification.
Specifically, the current DWARF draft specification seems to require that
the type of an non-unsigned integral bit-field member of a struct or union
the type of a non-unsigned integral bit-field member of a struct or union
type be represented as either a "signed" type or as a "plain" type,
depending upon the exact set of keywords that were used in the
type specification for the given bit-field member. It was felt (by the
@ -523,7 +523,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
are still being discussed. Also, we in the PLSIG are still discussing
whether or not we need to do anything special for C++ templates. (At this
time it is not yet clear whether we even need to do anything special for
these.)
these.)
With regard to FORTRAN, the UI/PLSIG has defined what is believed to be a
complete and sufficient set of codes and rules for adequately representing
@ -560,7 +560,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
Other possible `compacting' transformations designed to save disk
space and to reduce linker & debugger I/O activity.
*/
*/
#include "config.h"
@ -569,6 +569,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "dwarf.h"
#include "tree.h"
#include "flags.h"
#include "function.h"
#include "rtl.h"
#include "hard-reg-set.h"
#include "insn-config.h"
@ -599,7 +600,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
fprintf ((FILE), "%s", reg_names[REGNO (RTX)])
#endif
/* Define a macro which returns non-zero for any tagged type which is
/* Define a macro which returns nonzero for any tagged type which is
used (directly or indirectly) in the specification of either some
function's return type or some formal parameter of some function.
We use this macro when we are operating in "terse" mode to help us
@ -611,12 +612,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
for these nodes. For now, we have to just fake it. It it safe for
us to simply return zero for all complete tagged types (which will
get forced out anyway if they were used in the specification of some
formal or return type) and non-zero for all incomplete tagged types.
formal or return type) and nonzero for all incomplete tagged types.
*/
#define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
/* Define a macro which returns non-zero for a TYPE_DECL which was
/* Define a macro which returns nonzero for a TYPE_DECL which was
implicitly generated for a tagged type.
Note that unlike the gcc front end (which generates a NULL named
@ -631,8 +632,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
&& is_tagged_type (TREE_TYPE (decl)) \
&& decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
extern int flag_traditional;
/* Maximum size (in bytes) of an artificially generated label. */
#define MAX_ARTIFICIAL_LABEL_BYTES 30
@ -708,7 +707,7 @@ static unsigned pending_siblings_allocated;
#define PENDING_SIBLINGS_INCREMENT 64
/* Non-zero if we are performing our file-scope finalization pass and if
/* Nonzero if we are performing our file-scope finalization pass and if
we should force out Dwarf descriptions of any and all file-scope
tagged types which are still incomplete types. */
@ -758,14 +757,6 @@ static unsigned incomplete_types;
static tree fake_containing_scope;
/* The number of the current function definition that we are generating
debugging information for. These numbers range from 1 up to the maximum
number of function definitions contained within the current compilation
unit. These numbers are used to create unique labels for various things
contained within various function definitions. */
static unsigned current_funcdef_number = 1;
/* A pointer to the ..._DECL node which we have most recently been working
on. We keep this around just in case something about it looks screwy
and we want to tell the user what the source coordinates for the actual
@ -791,9 +782,9 @@ static void dwarfout_end_source_file PARAMS ((unsigned));
static void dwarfout_end_source_file_check PARAMS ((unsigned));
static void dwarfout_begin_block PARAMS ((unsigned, unsigned));
static void dwarfout_end_block PARAMS ((unsigned, unsigned));
static void dwarfout_end_epilogue PARAMS ((void));
static void dwarfout_end_epilogue PARAMS ((unsigned int, const char *));
static void dwarfout_source_line PARAMS ((unsigned int, const char *));
static void dwarfout_end_prologue PARAMS ((unsigned int));
static void dwarfout_end_prologue PARAMS ((unsigned int, const char *));
static void dwarfout_end_function PARAMS ((unsigned int));
static void dwarfout_function_decl PARAMS ((tree));
static void dwarfout_global_decl PARAMS ((tree));
@ -944,9 +935,6 @@ static void retry_incomplete_types PARAMS ((void));
#ifndef FILE_ASM_OP
#define FILE_ASM_OP "\t.file\t"
#endif
#ifndef VERSION_ASM_OP
#define VERSION_ASM_OP "\t.version\t"
#endif
#ifndef SET_ASM_OP
#define SET_ASM_OP "\t.set\t"
#endif
@ -1150,18 +1138,6 @@ static void retry_incomplete_types PARAMS ((void));
#ifndef BOUND_END_LABEL_FMT
#define BOUND_END_LABEL_FMT "*.L_b%u_%u_%c_e"
#endif
#ifndef DERIV_BEGIN_LABEL_FMT
#define DERIV_BEGIN_LABEL_FMT "*.L_d%u"
#endif
#ifndef DERIV_END_LABEL_FMT
#define DERIV_END_LABEL_FMT "*.L_d%u_e"
#endif
#ifndef SL_BEGIN_LABEL_FMT
#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
#endif
#ifndef SL_END_LABEL_FMT
#define SL_END_LABEL_FMT "*.L_sl%u_e"
#endif
#ifndef BODY_BEGIN_LABEL_FMT
#define BODY_BEGIN_LABEL_FMT "*.L_b%u"
#endif
@ -1289,12 +1265,12 @@ static void retry_incomplete_types PARAMS ((void));
ASM_OUTPUT_ASCII ((FILE), P, strlen (P)+1)
#else
#define ASM_OUTPUT_DWARF_STRING_NEWLINE(FILE,P) \
ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
ASM_OUTPUT_DWARF_STRING (FILE,P), ASM_OUTPUT_DWARF_STRING (FILE,"\n")
#endif
/* The debug hooks structure. */
struct gcc_debug_hooks dwarf_debug_hooks =
const struct gcc_debug_hooks dwarf_debug_hooks =
{
dwarfout_init,
dwarfout_finish,
@ -1325,7 +1301,7 @@ is_pseudo_reg (rtl)
rtx rtl;
{
return (((GET_CODE (rtl) == REG) && (REGNO (rtl) >= FIRST_PSEUDO_REGISTER))
|| ((GET_CODE (rtl) == SUBREG)
|| ((GET_CODE (rtl) == SUBREG)
&& (REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)));
}
@ -1343,13 +1319,13 @@ type_main_variant (type)
if (TREE_CODE (type) == ARRAY_TYPE)
{
while (type != TYPE_MAIN_VARIANT (type))
type = TYPE_MAIN_VARIANT (type);
type = TYPE_MAIN_VARIANT (type);
}
return type;
}
/* Return non-zero if the given type node represents a tagged type. */
/* Return nonzero if the given type node represents a tagged type. */
static inline int
is_tagged_type (type)
@ -1609,7 +1585,7 @@ static tree
decl_ultimate_origin (decl)
tree decl;
{
#ifdef ENABLE_CHECKING
#ifdef ENABLE_CHECKING
if (DECL_FROM_INLINE (DECL_ORIGIN (decl)))
/* Since the DECL_ABSTRACT_ORIGIN for a DECL is supposed to be the
most distant ancestor, this should never happen. */
@ -1707,7 +1683,7 @@ output_signed_leb128 (value)
if (negative)
value |= 0xfe000000; /* manually sign extend */
if (((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) == 1)))
|| ((value == -1) && ((byte & 0x40) == 1)))
more = 0;
else
{
@ -1974,7 +1950,7 @@ write_modifier_bytes (type, decl_const, decl_volatile)
write_modifier_bytes_1 (type, decl_const, decl_volatile, 0);
}
/* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
/* Given a pointer to an arbitrary ..._TYPE tree node, return nonzero if the
given input type is a Dwarf "fundamental" type. Otherwise return zero. */
static inline int
@ -2843,8 +2819,8 @@ location_or_const_value_attribute (decl)
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
/* This decl represents a formal parameter which was optimized out. */
tree declared_type = type_main_variant (TREE_TYPE (decl));
tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
tree declared_type = type_main_variant (TREE_TYPE (decl));
tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
/* Note that DECL_INCOMING_RTL may be NULL in here, but we handle
*all* cases where (rtl == NULL_RTX) just below. */
@ -3330,6 +3306,13 @@ member_attribute (context)
}
#if 0
#ifndef SL_BEGIN_LABEL_FMT
#define SL_BEGIN_LABEL_FMT "*.L_sl%u"
#endif
#ifndef SL_END_LABEL_FMT
#define SL_END_LABEL_FMT "*.L_sl%u_e"
#endif
static inline void
string_length_attribute (upper_bound)
tree upper_bound;
@ -3468,10 +3451,10 @@ pure_or_virtual_attribute (func_decl)
{
#if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific. */
if (DECL_ABSTRACT_VIRTUAL_P (func_decl))
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
else
#endif
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
@ -3510,7 +3493,7 @@ name_and_src_coords_attributes (decl)
file_index = lookup_filename (DECL_SOURCE_FILE (decl));
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SECTION);
src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
src_coords_attribute (file_index, DECL_SOURCE_LINE (decl));
}
#endif /* defined(DWARF_DECL_COORDINATES) */
}
@ -3591,7 +3574,7 @@ type_tag (type)
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
t = TYPE_NAME (type);
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
a TYPE_DECL node, regardless of whether or not a `typedef' was
involved. */
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
@ -3898,13 +3881,14 @@ output_global_subroutine_die (arg)
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_BEGIN_LABEL_FMT,
current_function_funcdef_no);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
body_end_attribute (label);
}
}
@ -4154,8 +4138,6 @@ output_compile_unit_die (arg)
language_attribute (LANG_PASCAL83);
else if (strcmp (language_string, "GNU Java") == 0)
language_attribute (LANG_JAVA);
else if (flag_traditional)
language_attribute (LANG_C);
else
language_attribute (LANG_C89);
low_pc_attribute (TEXT_BEGIN_LABEL);
@ -4174,7 +4156,7 @@ output_compile_unit_die (arg)
sf_names_attribute (SFNAMES_BEGIN_LABEL);
src_info_attribute (SRCINFO_BEGIN_LABEL);
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
mac_info_attribute (MACINFO_BEGIN_LABEL);
mac_info_attribute (MACINFO_BEGIN_LABEL);
}
}
@ -4217,7 +4199,7 @@ output_inheritance_die (arg)
ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
}
}
}
static void
output_structure_type_die (arg)
@ -4281,13 +4263,14 @@ output_local_subroutine_die (arg)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
high_pc_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_BEGIN_LABEL_FMT,
current_function_funcdef_no);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
body_end_attribute (label);
}
}
@ -4550,7 +4533,7 @@ pend_type (type)
TREE_ASM_WRITTEN (type) = 1;
}
/* Return non-zero if it is legitimate to output DIEs to represent a
/* Return nonzero if it is legitimate to output DIEs to represent a
given type while we are generating the list of child DIEs for some
DIE (e.g. a function or lexical block DIE) associated with a given scope.
@ -4801,7 +4784,7 @@ output_type (type, containing_scope)
end_sibling_chain ();
break;
case ARRAY_TYPE:
case ARRAY_TYPE:
if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE)
{
output_type (TREE_TYPE (type), containing_scope);
@ -5156,8 +5139,8 @@ output_decls_for_scope (stmt, depth)
tree subblocks;
for (subblocks = BLOCK_SUBBLOCKS (stmt);
subblocks;
subblocks = BLOCK_CHAIN (subblocks))
subblocks;
subblocks = BLOCK_CHAIN (subblocks))
output_block (subblocks, depth + 1);
}
}
@ -5203,10 +5186,10 @@ output_decl (decl, containing_scope)
if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
|| TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
&& ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0)
|| (TYPE_FIELDS (TREE_TYPE (decl))
|| (TYPE_FIELDS (TREE_TYPE (decl))
&& (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK))))
return;
/* If this ..._DECL node is marked to be ignored, then ignore it. */
if (DECL_IGNORED_P (decl))
@ -5331,7 +5314,7 @@ output_decl (decl, containing_scope)
for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
{
{
if (DECL_NAME(parm) &&
!strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
"__builtin_va_alist") )
@ -5368,13 +5351,13 @@ output_decl (decl, containing_scope)
/* this is the prototyped case, check for ... */
if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
output_die (output_unspecified_parameters_die, decl);
}
else
{
/* this is unprototyped, check for undefined (just declaration) */
if (!DECL_INITIAL (decl))
output_die (output_unspecified_parameters_die, decl);
}
}
else
{
/* this is unprototyped, check for undefined (just declaration) */
if (!DECL_INITIAL (decl))
output_die (output_unspecified_parameters_die, decl);
}
}
/* Output Dwarf info for all of the stuff within the body of the
@ -5433,7 +5416,7 @@ output_decl (decl, containing_scope)
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
return;
return;
/* In the special case of a TYPE_DECL node representing
the declaration of some type tag, if the given TYPE_DECL is
@ -5474,7 +5457,7 @@ output_decl (decl, containing_scope)
any variable declarations or definitions. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
break;
break;
/* Output any DIEs that are needed to specify the type of this data
object. */
@ -5508,7 +5491,7 @@ output_decl (decl, containing_scope)
function. */
{
void (*func) PARAMS ((void *));
void (*func) PARAMS ((void *));
register tree origin = decl_ultimate_origin (decl);
if (origin != NULL && TREE_CODE (origin) == PARM_DECL)
@ -5529,7 +5512,7 @@ output_decl (decl, containing_scope)
if (DECL_NAME (decl) != 0)
{
output_type (member_declared_type (decl), containing_scope);
output_die (output_member_die, decl);
output_die (output_member_die, decl);
}
break;
@ -5629,7 +5612,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
these same functions should NOT be ignored however. */
if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
return;
return;
/* What we would really like to do here is to filter out all mere
file-scope declarations of file-scope functions which are never
@ -5729,7 +5712,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file,
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
(unsigned) int_size_in_bytes (TREE_TYPE (decl)));
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@ -5739,7 +5722,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
any variable declarations or definitions. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
return;
return;
break;
@ -5777,7 +5760,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (! TYPE_DECL_IS_STUB (decl)
|| ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
return;
return;
break;
@ -5807,7 +5790,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
if this is not a nested function or class. If this is a nested type,
then the remaining pending_types will be emitted when the containing type
is handled. */
if (! DECL_CONTEXT (decl))
{
if (pending_types != 0)
@ -5815,9 +5798,6 @@ dwarfout_file_scope_decl (decl, set_finalizing)
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) != NULL)
current_funcdef_number++;
}
/* Output a marker (i.e. a label) for the beginning of the generated code
@ -5855,8 +5835,9 @@ dwarfout_end_block (line, blocknum)
to their home locations). */
static void
dwarfout_end_prologue (line)
dwarfout_end_prologue (line, file)
unsigned int line ATTRIBUTE_UNUSED;
const char *file ATTRIBUTE_UNUSED;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
@ -5864,7 +5845,7 @@ dwarfout_end_prologue (line)
return;
function_section (current_function_decl);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@ -5880,7 +5861,7 @@ dwarfout_end_function (line)
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
sprintf (label, BODY_END_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@ -5889,14 +5870,16 @@ dwarfout_end_function (line)
has been generated. */
static void
dwarfout_end_epilogue ()
dwarfout_end_epilogue (line, file)
unsigned int line ATTRIBUTE_UNUSED;
const char *file ATTRIBUTE_UNUSED;
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
function. */
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
sprintf (label, FUNC_END_LABEL_FMT, current_function_funcdef_no);
ASM_OUTPUT_LABEL (asm_out_file, label);
}
@ -5936,9 +5919,9 @@ generate_new_sfname_entry ()
sprintf (label, SFNAMES_ENTRY_LABEL_FMT, filename_table[0].number);
ASM_OUTPUT_LABEL (asm_out_file, label);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file,
filename_table[0].name
? filename_table[0].name
: "");
filename_table[0].name
? filename_table[0].name
: "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
@ -5990,7 +5973,7 @@ lookup_filename (file_name)
same filename will find it as quickly as possible. */
shuffle_filename_entry (search_p);
return filename_table[0].number;
return filename_table[0].number;
}
/* We come here whenever we have a new filename which is not registered
@ -6068,18 +6051,18 @@ dwarfout_source_line (line, filename)
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
if (this_file_entry_num != prev_file_entry_num)
{
char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
{
char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num);
ASM_OUTPUT_LABEL (asm_out_file, line_entry_label);
}
sprintf (line_entry_label, LINE_ENTRY_LABEL_FMT, last_line_entry_num);
ASM_OUTPUT_LABEL (asm_out_file, line_entry_label);
}
{
const char *tail = strrchr (filename, '/');
const char *tail = strrchr (filename, '/');
if (tail != NULL)
filename = tail;
if (tail != NULL)
filename = tail;
}
dw2_asm_output_data (4, line, "%s:%u", filename, line);
@ -6088,7 +6071,7 @@ dwarfout_source_line (line, filename)
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (this_file_entry_num != prev_file_entry_num)
generate_srcinfo_entry (last_line_entry_num, this_file_entry_num);
generate_srcinfo_entry (last_line_entry_num, this_file_entry_num);
prev_file_entry_num = this_file_entry_num;
}
}
@ -6195,6 +6178,8 @@ static void
dwarfout_init (main_input_filename)
const char *main_input_filename;
{
warning ("support for the DWARF1 debugging format is deprecated");
/* Remember the name of the primary input file. */
primary_filename = main_input_filename;
@ -6281,7 +6266,7 @@ dwarfout_init (main_input_filename)
/* Output a starting label and an initial (compilation directory)
entry for the .debug_sfnames section. The starting label will be
referenced by the initial entry in the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_SFNAMES_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
@ -6298,29 +6283,29 @@ dwarfout_init (main_input_filename)
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (debug_info_level >= DINFO_LEVEL_VERBOSE
&& use_gnu_debug_info_extensions)
{
/* Output a starting label for the .debug_macinfo section. This
/* Output a starting label for the .debug_macinfo section. This
label will be referenced by the AT_mac_info attribute in the
TAG_compile_unit DIE. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_MACINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, MACINFO_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
/* Generate the initial entry for the .line section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, LINE_END_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (use_gnu_debug_info_extensions)
{
/* Generate the initial entry for the .debug_srcinfo section. */
@ -6339,16 +6324,16 @@ dwarfout_init (main_input_filename)
#endif
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
/* Generate the initial entry for the .debug_pubnames section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, DEBUG_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
/* Generate the initial entry for the .debug_aranges section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
@ -6474,7 +6459,7 @@ dwarfout_finish (main_input_filename)
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
/* Output a terminating entry for the .line section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, LINE_LAST_ENTRY_LABEL);
@ -6483,7 +6468,7 @@ dwarfout_finish (main_input_filename)
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, TEXT_END_LABEL, TEXT_BEGIN_LABEL);
ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (use_gnu_debug_info_extensions)
{
/* Output a terminating entry for the .debug_srcinfo section. */
@ -6499,7 +6484,7 @@ dwarfout_finish (main_input_filename)
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
/* Output terminating entries for the .debug_macinfo section. */
dwarfout_end_source_file (0);
fputc ('\n', asm_out_file);
@ -6508,15 +6493,15 @@ dwarfout_finish (main_input_filename)
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
/* Generate the terminating entry for the .debug_pubnames section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, 0);
ASM_OUTPUT_DWARF_STRING_NEWLINE (asm_out_file, "");
ASM_OUTPUT_POP_SECTION (asm_out_file);
/* Generate the terminating entries for the .debug_aranges section.
Note that we want to do this only *after* we have output the end
@ -6530,7 +6515,7 @@ dwarfout_finish (main_input_filename)
entries at this late point in the assembly output, we skirt the
issue simply by avoiding forward-references.
*/
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, DEBUG_ARANGES_SECTION);

File diff suppressed because it is too large Load Diff

View File

@ -68,6 +68,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "target.h"
#include "debug.h"
#include "expr.h"
#include "profile.h"
#include "cfglayout.h"
#ifdef XCOFF_DEBUGGING_INFO
#include "xcoffout.h" /* Needed for external data
@ -98,6 +100,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define JUMP_TABLES_IN_TEXT_SECTION 0
#endif
#if defined(READONLY_DATA_SECTION) || defined(READONLY_DATA_SECTION_ASM_OP)
#define HAVE_READONLY_DATA_SECTION 1
#else
#define HAVE_READONLY_DATA_SECTION 0
#endif
/* Last insn processed by final_scan_insn. */
static rtx debug_insn;
rtx current_output_insn;
@ -114,15 +122,12 @@ static int high_function_linenum;
/* Filename of last NOTE. */
static const char *last_filename;
/* Number of instrumented arcs when profile_arc_flag is set. */
extern int count_instrumented_edges;
extern int length_unit_log; /* This is defined in insn-attrtab.c. */
/* Nonzero while outputting an `asm' with operands.
This means that inconsistencies are the user's fault, so don't abort.
The precise value is the insn being output, to pass to error_for_asm. */
static rtx this_is_asm_operands;
rtx this_is_asm_operands;
/* Number of operands of this insn, for an `asm' with operands. */
static unsigned int insn_noperands;
@ -198,6 +203,17 @@ static char *line_note_exists;
rtx current_insn_predicate;
#endif
struct function_list
{
struct function_list *next; /* next function */
const char *name; /* function name */
long cfg_checksum; /* function checksum */
long count_edges; /* number of intrumented edges in this function */
};
static struct function_list *functions_head = 0;
static struct function_list **functions_tail = &functions_head;
#ifdef HAVE_ATTR_length
static int asm_insn_count PARAMS ((rtx));
#endif
@ -206,6 +222,7 @@ static void profile_after_prologue PARAMS ((FILE *));
static void notice_source_line PARAMS ((rtx));
static rtx walk_alter_subreg PARAMS ((rtx *));
static void output_asm_name PARAMS ((void));
static void output_alternate_entry_point PARAMS ((FILE *, rtx));
static tree get_mem_expr_from_op PARAMS ((rtx, int *));
static void output_asm_operand_names PARAMS ((rtx *, int *, int));
static void output_operand PARAMS ((rtx, int));
@ -237,137 +254,268 @@ init_final (filename)
}
/* Called at end of source file,
to output the block-profiling table for this entire compilation. */
to output the arc-profiling table for this entire compilation. */
void
end_final (filename)
const char *filename;
{
if (profile_arc_flag)
if (profile_arc_flag && profile_info.count_instrumented_edges)
{
char name[20];
int align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
int size, rounded;
int long_bytes = LONG_TYPE_SIZE / BITS_PER_UNIT;
int gcov_type_bytes = GCOV_TYPE_SIZE / BITS_PER_UNIT;
int pointer_bytes = POINTER_SIZE / BITS_PER_UNIT;
unsigned int align2 = LONG_TYPE_SIZE;
tree string_type, string_cst;
tree structure_decl, structure_value, structure_pointer_type;
tree field_decl, decl_chain, value_chain;
tree sizeof_field_value, domain_type;
size = gcov_type_bytes * count_instrumented_edges;
rounded = size;
/* Build types. */
string_type = build_pointer_type (char_type_node);
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
* (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
/* Libgcc2 bb structure. */
structure_decl = make_node (RECORD_TYPE);
structure_pointer_type = build_pointer_type (structure_decl);
/* ??? This _really_ ought to be done with a structure layout
and with assemble_constructor. If long_bytes != pointer_bytes
we'll be emitting unaligned data at some point. */
if (long_bytes != pointer_bytes)
abort ();
data_section ();
/* Output the main header, of 11 words:
0: 1 if this file is initialized, else 0.
1: address of file name (LPBX1).
2: address of table of counts (LPBX2).
3: number of counts in the table.
4: always 0, for compatibility with Sun.
/* Output the main header, of 7 words:
0: 1 if this file is initialized, else 0.
1: address of file name (LPBX1).
2: address of table of counts (LPBX2).
3: number of counts in the table.
4: always 0, libgcc2 uses this as a pointer to next ``struct bb''
The following are GNU extensions:
5: address of table of start addrs of basic blocks (LPBX3).
6: Number of bytes in this header.
7: address of table of function names (LPBX4).
8: address of table of line numbers (LPBX5) or 0.
9: address of table of file names (LPBX6) or 0.
10: space reserved for basic block profiling. */
5: Number of bytes in this header.
6: address of table of function checksums (LPBX7). */
ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 0);
/* Zero word. */
assemble_integer (const0_rtx, long_bytes, align2, 1);
/* The zero word. */
decl_chain =
build_decl (FIELD_DECL, get_identifier ("zero_word"),
long_integer_type_node);
value_chain = build_tree_list (decl_chain,
convert (long_integer_type_node,
integer_zero_node));
/* Address of filename. */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 1);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
align2, 1);
/* Address of count table. */
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
assemble_integer (gen_rtx_SYMBOL_REF (Pmode, name), pointer_bytes,
align2, 1);
/* Count of the # of instrumented arcs. */
assemble_integer (GEN_INT (count_instrumented_edges),
long_bytes, align2, 1);
/* Zero word (link field). */
assemble_integer (const0_rtx, pointer_bytes, align2, 1);
assemble_integer (const0_rtx, pointer_bytes, align2, 1);
/* Byte count for extended structure. */
assemble_integer (GEN_INT (11 * UNITS_PER_WORD), long_bytes, align2, 1);
/* Address of function name table. */
assemble_integer (const0_rtx, pointer_bytes, align2, 1);
/* Address of line number and filename tables if debugging. */
assemble_integer (const0_rtx, pointer_bytes, align2, 1);
assemble_integer (const0_rtx, pointer_bytes, align2, 1);
/* Space for extension ptr (link field). */
assemble_integer (const0_rtx, UNITS_PER_WORD, align2, 1);
/* Output the file name changing the suffix to .d for
Sun tcov compatibility. */
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 1);
{
char *cwd = getpwd ();
int len = strlen (filename) + strlen (cwd) + 1;
char *data_file = (char *) alloca (len + 4);
char *cwd, *da_filename;
int da_filename_len;
strcpy (data_file, cwd);
strcat (data_file, "/");
strcat (data_file, filename);
strip_off_ending (data_file, len);
strcat (data_file, ".da");
assemble_string (data_file, strlen (data_file) + 1);
field_decl =
build_decl (FIELD_DECL, get_identifier ("filename"), string_type);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
cwd = getpwd ();
da_filename_len = strlen (filename) + strlen (cwd) + 4 + 1;
da_filename = (char *) alloca (da_filename_len);
strcpy (da_filename, cwd);
strcat (da_filename, "/");
strcat (da_filename, filename);
strcat (da_filename, ".da");
da_filename_len = strlen (da_filename);
string_cst = build_string (da_filename_len + 1, da_filename);
domain_type = build_index_type (build_int_2 (da_filename_len, 0));
TREE_TYPE (string_cst)
= build_array_type (char_type_node, domain_type);
value_chain = tree_cons (field_decl,
build1 (ADDR_EXPR, string_type, string_cst),
value_chain);
}
/* Make space for the table of counts. */
if (size == 0)
{
/* Realign data section. */
ASM_OUTPUT_ALIGN (asm_out_file, align);
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LPBX", 2);
if (size != 0)
assemble_zeros (size);
}
else
{
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
#ifdef ASM_OUTPUT_SHARED_LOCAL
if (flag_shared_data)
ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
else
#endif
#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name,
size, BIGGEST_ALIGNMENT);
#else
#ifdef ASM_OUTPUT_ALIGNED_LOCAL
ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size,
BIGGEST_ALIGNMENT);
#else
ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
#endif
#endif
}
/* Table of counts. */
{
tree gcov_type_type = make_unsigned_type (GCOV_TYPE_SIZE);
tree gcov_type_pointer_type = build_pointer_type (gcov_type_type);
tree domain_tree
= build_index_type (build_int_2 (profile_info.
count_instrumented_edges - 1, 0));
tree gcov_type_array_type
= build_array_type (gcov_type_type, domain_tree);
tree gcov_type_array_pointer_type
= build_pointer_type (gcov_type_array_type);
tree counts_table;
field_decl =
build_decl (FIELD_DECL, get_identifier ("counts"),
gcov_type_pointer_type);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
/* No values. */
counts_table
= build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
TREE_STATIC (counts_table) = 1;
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 2);
DECL_NAME (counts_table) = get_identifier (name);
assemble_variable (counts_table, 0, 0, 0);
value_chain = tree_cons (field_decl,
build1 (ADDR_EXPR,
gcov_type_array_pointer_type,
counts_table), value_chain);
}
/* Count of the # of instrumented arcs. */
field_decl
= build_decl (FIELD_DECL, get_identifier ("ncounts"),
long_integer_type_node);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
value_chain = tree_cons (field_decl,
convert (long_integer_type_node,
build_int_2 (profile_info.
count_instrumented_edges,
0)), value_chain);
/* Pointer to the next bb. */
field_decl
= build_decl (FIELD_DECL, get_identifier ("next"),
structure_pointer_type);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
value_chain = tree_cons (field_decl, null_pointer_node, value_chain);
/* sizeof(struct bb). We'll set this after entire structure
is laid out. */
field_decl
= build_decl (FIELD_DECL, get_identifier ("sizeof_bb"),
long_integer_type_node);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
sizeof_field_value = tree_cons (field_decl, NULL, value_chain);
value_chain = sizeof_field_value;
/* struct bb_function []. */
{
struct function_list *item;
int num_nodes;
tree checksum_field, arc_count_field, name_field;
tree domain;
tree array_value_chain = NULL_TREE;
tree bb_fn_struct_type;
tree bb_fn_struct_array_type;
tree bb_fn_struct_array_pointer_type;
tree bb_fn_struct_pointer_type;
tree field_value, field_value_chain;
bb_fn_struct_type = make_node (RECORD_TYPE);
checksum_field = build_decl (FIELD_DECL, get_identifier ("checksum"),
long_integer_type_node);
arc_count_field
= build_decl (FIELD_DECL, get_identifier ("arc_count"),
integer_type_node);
TREE_CHAIN (checksum_field) = arc_count_field;
name_field
= build_decl (FIELD_DECL, get_identifier ("name"), string_type);
TREE_CHAIN (arc_count_field) = name_field;
TYPE_FIELDS (bb_fn_struct_type) = checksum_field;
num_nodes = 0;
for (item = functions_head; item != 0; item = item->next)
num_nodes++;
/* Note that the array contains a terminator, hence no - 1. */
domain = build_index_type (build_int_2 (num_nodes, 0));
bb_fn_struct_pointer_type = build_pointer_type (bb_fn_struct_type);
bb_fn_struct_array_type
= build_array_type (bb_fn_struct_type, domain);
bb_fn_struct_array_pointer_type
= build_pointer_type (bb_fn_struct_array_type);
layout_type (bb_fn_struct_type);
layout_type (bb_fn_struct_pointer_type);
layout_type (bb_fn_struct_array_type);
layout_type (bb_fn_struct_array_pointer_type);
for (item = functions_head; item != 0; item = item->next)
{
size_t name_len;
/* create constructor for structure. */
field_value_chain
= build_tree_list (checksum_field,
convert (long_integer_type_node,
build_int_2 (item->cfg_checksum, 0)));
field_value_chain
= tree_cons (arc_count_field,
convert (integer_type_node,
build_int_2 (item->count_edges, 0)),
field_value_chain);
name_len = strlen (item->name);
string_cst = build_string (name_len + 1, item->name);
domain_type = build_index_type (build_int_2 (name_len, 0));
TREE_TYPE (string_cst)
= build_array_type (char_type_node, domain_type);
field_value_chain = tree_cons (name_field,
build1 (ADDR_EXPR, string_type,
string_cst),
field_value_chain);
/* Add to chain. */
array_value_chain
= tree_cons (NULL_TREE, build (CONSTRUCTOR,
bb_fn_struct_type, NULL_TREE,
nreverse (field_value_chain)),
array_value_chain);
}
/* Add terminator. */
field_value = build_tree_list (arc_count_field,
convert (integer_type_node,
build_int_2 (-1, 0)));
array_value_chain = tree_cons (NULL_TREE,
build (CONSTRUCTOR, bb_fn_struct_type,
NULL_TREE, field_value),
array_value_chain);
/* Create constructor for array. */
field_decl
= build_decl (FIELD_DECL, get_identifier ("function_infos"),
bb_fn_struct_pointer_type);
value_chain = tree_cons (field_decl,
build1 (ADDR_EXPR,
bb_fn_struct_array_pointer_type,
build (CONSTRUCTOR,
bb_fn_struct_array_type,
NULL_TREE,
nreverse
(array_value_chain))),
value_chain);
TREE_CHAIN (field_decl) = decl_chain;
decl_chain = field_decl;
}
/* Finish structure. */
TYPE_FIELDS (structure_decl) = nreverse (decl_chain);
layout_type (structure_decl);
structure_value
= build (VAR_DECL, structure_decl, NULL_TREE, NULL_TREE);
DECL_INITIAL (structure_value)
= build (CONSTRUCTOR, structure_decl, NULL_TREE,
nreverse (value_chain));
TREE_STATIC (structure_value) = 1;
ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
DECL_NAME (structure_value) = get_identifier (name);
/* Size of this structure. */
TREE_VALUE (sizeof_field_value)
= convert (long_integer_type_node,
build_int_2 (int_size_in_bytes (structure_decl), 0));
/* Build structure. */
assemble_variable (structure_value, 0, 0, 0);
}
}
@ -438,9 +586,7 @@ dbr_sequence_length ()
static int *insn_lengths;
#ifdef HAVE_ATTR_length
varray_type insn_addresses_;
#endif
/* Max uid for which the above arrays are valid. */
static int insn_lengths_max_uid;
@ -527,7 +673,7 @@ get_attr_length (insn)
case JUMP_INSN:
body = PATTERN (insn);
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
if (GET_CODE (body) == ADDR_VEC || GET_CODE (body) == ADDR_DIFF_VEC)
{
/* Alignment is machine-dependent and should be handled by
ADDR_VEC_ALIGN. */
@ -787,8 +933,8 @@ insn_current_reference_address (branch)
void
compute_alignments ()
{
int i;
int log, max_skip, max_log;
basic_block bb;
if (label_align)
{
@ -805,9 +951,8 @@ compute_alignments ()
if (! optimize || optimize_size)
return;
for (i = 0; i < n_basic_blocks; i++)
FOR_EACH_BB (bb)
{
basic_block bb = BASIC_BLOCK (i);
rtx label = bb->head;
int fallthru_frequency = 0, branch_frequency = 0, has_fallthru = 0;
edge e;
@ -837,8 +982,8 @@ compute_alignments ()
if (!has_fallthru
&& (branch_frequency > BB_FREQ_MAX / 10
|| (bb->frequency > BASIC_BLOCK (i - 1)->frequency * 10
&& (BASIC_BLOCK (i - 1)->frequency
|| (bb->frequency > bb->prev_bb->frequency * 10
&& (bb->prev_bb->frequency
<= ENTRY_BLOCK_PTR->frequency / 2))))
{
log = JUMP_ALIGN (label);
@ -849,10 +994,10 @@ compute_alignments ()
}
}
/* In case block is frequent and reached mostly by non-fallthru edge,
align it. It is most likely an first block of loop. */
align it. It is most likely a first block of loop. */
if (has_fallthru
&& branch_frequency + fallthru_frequency > BB_FREQ_MAX / 10
&& branch_frequency > fallthru_frequency * 5)
&& branch_frequency > fallthru_frequency * 2)
{
log = LOOP_ALIGN (label);
if (max_log < log)
@ -974,11 +1119,7 @@ shorten_branches (first)
next = NEXT_INSN (insn);
/* ADDR_VECs only take room if read-only data goes into the text
section. */
if (JUMP_TABLES_IN_TEXT_SECTION
#if !defined(READONLY_DATA_SECTION)
|| 1
#endif
)
if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
if (next && GET_CODE (next) == JUMP_INSN)
{
rtx nextbody = PATTERN (next);
@ -1128,7 +1269,7 @@ shorten_branches (first)
}
}
INSN_ADDRESSES (uid) = insn_current_address;
INSN_ADDRESSES (uid) = insn_current_address + insn_lengths[uid];
if (GET_CODE (insn) == NOTE || GET_CODE (insn) == BARRIER
|| GET_CODE (insn) == CODE_LABEL)
@ -1141,11 +1282,7 @@ shorten_branches (first)
{
/* This only takes room if read-only data goes into the text
section. */
if (JUMP_TABLES_IN_TEXT_SECTION
#if !defined(READONLY_DATA_SECTION)
|| 1
#endif
)
if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
insn_lengths[uid] = (XVECLEN (body,
GET_CODE (body) == ADDR_DIFF_VEC)
* GET_MODE_SIZE (GET_MODE (body)));
@ -1346,11 +1483,7 @@ shorten_branches (first)
PUT_MODE (body, CASE_VECTOR_SHORTEN_MODE (min_addr - rel_addr,
max_addr - rel_addr,
body));
if (JUMP_TABLES_IN_TEXT_SECTION
#if !defined(READONLY_DATA_SECTION)
|| 1
#endif
)
if (JUMP_TABLES_IN_TEXT_SECTION || !HAVE_READONLY_DATA_SECTION)
{
insn_lengths[uid]
= (XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body)));
@ -1380,7 +1513,7 @@ shorten_branches (first)
insn_current_address += insn_lengths[inner_uid];
}
}
}
else
insn_current_address += insn_lengths[uid];
@ -1537,7 +1670,7 @@ final_start_function (first, file, optimize)
if (write_symbols)
{
remove_unnecessary_notes ();
reorder_blocks ();
scope_to_insns_finalize ();
number_blocks (current_function_decl);
/* We never actually put out begin/end notes for the top-level
block in the function. But, conceptually, that block is
@ -1548,12 +1681,6 @@ final_start_function (first, file, optimize)
/* First output the function prologue: code to set up the stack frame. */
(*targetm.asm_out.function_prologue) (file, get_frame_size ());
#ifdef VMS_DEBUGGING_INFO
/* Output label after the prologue of the function. */
if (write_symbols == VMS_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG)
vmsdbgout_after_prologue ();
#endif
/* If the machine represents the prologue as RTL, the profiling code must
be emitted when NOTE_INSN_PROLOGUE_END is scanned. */
#ifdef HAVE_prologue
@ -1591,7 +1718,7 @@ profile_function (file)
#ifndef NO_PROFILE_COUNTERS
data_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_profile_label_no);
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", current_function_funcdef_no);
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, align, 1);
#endif
@ -1621,7 +1748,7 @@ profile_function (file)
#endif
#endif
FUNCTION_PROFILER (file, current_function_profile_label_no);
FUNCTION_PROFILER (file, current_function_funcdef_no);
#if defined(STATIC_CHAIN_INCOMING_REGNUM) && defined(ASM_OUTPUT_REG_PUSH)
if (cxt)
@ -1664,12 +1791,12 @@ final_end_function ()
(*targetm.asm_out.function_epilogue) (asm_out_file, get_frame_size ());
/* And debug output. */
(*debug_hooks->end_epilogue) ();
(*debug_hooks->end_epilogue) (last_linenum, last_filename);
#if defined (DWARF2_UNWIND_INFO)
if (write_symbols != DWARF2_DEBUG && write_symbols != VMS_AND_DWARF2_DEBUG
&& dwarf2out_do_frame ())
dwarf2out_end_epilogue ();
dwarf2out_end_epilogue (last_linenum, last_filename);
#endif
}
@ -1763,16 +1890,12 @@ final (first, file, optimize, prescan)
#ifdef HAVE_ATTR_length
if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
{
#ifdef STACK_REGS
/* Irritatingly, the reg-stack pass is creating new instructions
and because of REG_DEAD note abuse it has to run after
shorten_branches. Fake address of -1 then. */
insn_current_address = -1;
#else
/* This can be triggered by bugs elsewhere in the compiler if
new insns are created after init_insn_lengths is called. */
abort ();
#endif
if (GET_CODE (insn) == NOTE)
insn_current_address = -1;
else
abort ();
}
else
insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
@ -1781,6 +1904,23 @@ final (first, file, optimize, prescan)
insn = final_scan_insn (insn, file, optimize, prescan, 0);
}
/* Store function names for edge-profiling. */
/* ??? Probably should re-use the existing struct function. */
if (cfun->arc_profile)
{
struct function_list *new_item = xmalloc (sizeof (struct function_list));
*functions_tail = new_item;
functions_tail = &new_item->next;
new_item->next = 0;
new_item->name = xstrdup (IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (current_function_decl)));
new_item->cfg_checksum = profile_info.current_function_cfg_checksum;
new_item->count_edges = profile_info.count_edges_instrumented_now;
}
free (line_note_exists);
line_note_exists = NULL;
}
@ -1807,6 +1947,39 @@ get_insn_template (code, insn)
}
}
/* Emit the appropriate declaration for an alternate-entry-point
symbol represented by INSN, to FILE. INSN is a CODE_LABEL with
LABEL_KIND != LABEL_NORMAL.
The case fall-through in this function is intentional. */
static void
output_alternate_entry_point (file, insn)
FILE *file;
rtx insn;
{
const char *name = LABEL_NAME (insn);
switch (LABEL_KIND (insn))
{
case LABEL_WEAK_ENTRY:
#ifdef ASM_WEAKEN_LABEL
ASM_WEAKEN_LABEL (file, name);
#endif
case LABEL_GLOBAL_ENTRY:
(*targetm.asm_out.globalize_label) (file, name);
case LABEL_STATIC_ENTRY:
#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
#endif
ASM_OUTPUT_LABEL (file, name);
break;
case LABEL_NORMAL:
default:
abort ();
}
}
/* The final scan for one insn, INSN.
Args are same as in `final', except that INSN
is the insn being scanned.
@ -1850,9 +2023,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_LOOP_VTOP:
case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_RANGE_BEG:
case NOTE_INSN_RANGE_END:
case NOTE_INSN_LIVE:
case NOTE_INSN_EXPECTED_VALUE:
break;
@ -1886,7 +2056,7 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
case NOTE_INSN_FUNCTION_BEG:
app_disable ();
(*debug_hooks->end_prologue) (last_linenum);
(*debug_hooks->end_prologue) (last_linenum, last_filename);
break;
case NOTE_INSN_BLOCK_BEG:
@ -2015,8 +2185,12 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
{
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (file, align, max_skip);
#else
#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
ASM_OUTPUT_ALIGN_WITH_NOP (file, align);
#else
ASM_OUTPUT_ALIGN (file, align);
#endif
#endif
}
}
@ -2100,17 +2274,14 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
NEXT_INSN (insn));
#else
if (LABEL_ALTERNATE_NAME (insn))
ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
else
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
break;
}
}
if (LABEL_ALTERNATE_NAME (insn))
ASM_OUTPUT_ALTERNATE_LABEL_NAME (file, insn);
if (LABEL_ALT_ENTRY_P (insn))
output_alternate_entry_point (file, insn);
else
ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
break;
@ -2539,13 +2710,13 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes)
insn_code_number = recog_memoized (insn);
cleanup_subreg_operands (insn);
/* Dump the insn in the assembly for debugging. */
if (flag_dump_rtl_in_asm)
{
print_rtx_head = ASM_COMMENT_START;
print_rtl_single (asm_out_file, insn);
print_rtx_head = "";
}
/* Dump the insn in the assembly for debugging. */
if (flag_dump_rtl_in_asm)
{
print_rtx_head = ASM_COMMENT_START;
print_rtl_single (asm_out_file, insn);
print_rtx_head = "";
}
if (! constrain_operands_cached (1))
fatal_insn_not_found (insn);
@ -2755,7 +2926,7 @@ alter_subreg (xp)
ORIGINAL_REGNO (x) = ORIGINAL_REGNO (y);
/* This field has a different meaning for REGs and SUBREGs. Make
sure to clear it! */
x->used = 0;
RTX_FLAG (x, used) = 0;
}
else
abort ();
@ -2970,7 +3141,7 @@ output_operand_lossage VPARAMS ((const char *msgid, ...))
pfx_str = this_is_asm_operands ? _("invalid `asm': ") : "output_operand: ";
asprintf (&fmt_string, "%s%s", pfx_str, _(msgid));
vasprintf (&new_message, fmt_string, ap);
if (this_is_asm_operands)
error_for_asm (this_is_asm_operands, "%s", new_message);
else
@ -3768,7 +3939,6 @@ split_double (value, first, second)
}
else
{
#ifdef REAL_ARITHMETIC
REAL_VALUE_TYPE r;
long l[2];
REAL_VALUE_FROM_CONST_DOUBLE (r, value);
@ -3797,30 +3967,6 @@ split_double (value, first, second)
*first = GEN_INT ((HOST_WIDE_INT) l[0]);
*second = GEN_INT ((HOST_WIDE_INT) l[1]);
#else
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& ! flag_pretend_float)
abort ();
if (
#ifdef HOST_WORDS_BIG_ENDIAN
WORDS_BIG_ENDIAN
#else
! WORDS_BIG_ENDIAN
#endif
)
{
/* Host and target agree => no need to swap. */
*first = GEN_INT (CONST_DOUBLE_LOW (value));
*second = GEN_INT (CONST_DOUBLE_HIGH (value));
}
else
{
*second = GEN_INT (CONST_DOUBLE_LOW (value));
*first = GEN_INT (CONST_DOUBLE_HIGH (value));
}
#endif /* no REAL_ARITHMETIC */
}
}
@ -3865,7 +4011,7 @@ leaf_function_p ()
return 1;
}
/* Return 1 if branch is an forward branch.
/* Return 1 if branch is a forward branch.
Uses insn_shuid array, so it works only in the final pass. May be used by
output templates to customary add branch prediction hints.
*/

View File

@ -1,5 +1,5 @@
/* Compilation switch flag definitions for GCC.
Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000
Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
Free Software Foundation, Inc.
This file is part of GCC.
@ -126,10 +126,20 @@ extern int warn_unknown_pragmas;
extern int warn_shadow;
/* Warn if a switch on an enum fails to have a case for every enum value. */
/* Warn if a switch on an enum, that does not have a default case,
fails to have a case for every enum value. */
extern int warn_switch;
/* Warn if a switch does not have a default case. */
extern int warn_switch_default;
/* Warn if a switch on an enum fails to have a case for every enum
value (regardless of the presence or otherwise of a default case). */
extern int warn_switch_enum;
/* Nonzero means warn about function definitions that default the return type
or that use a null return and have a return-type other than void. */
@ -174,6 +184,11 @@ extern int warn_disabled_optimization;
extern int warn_deprecated_decl;
/* Nonzero means warn about constructs which might not be strict
aliasing safe. */
extern int warn_strict_aliasing;
/* Nonzero if generating code to do profiling. */
extern int profile_flag;
@ -194,6 +209,10 @@ extern int flag_branch_probabilities;
extern int flag_reorder_blocks;
/* Nonzero if functions should be reordered. */
extern int flag_reorder_functions;
/* Nonzero if registers should be renamed. */
extern int flag_rename_registers;
@ -345,6 +364,10 @@ extern int flag_errno_math;
extern int flag_unsafe_math_optimizations;
/* Nonzero means that no NaNs or +-Infs are expected. */
extern int flag_finite_math_only;
/* Zero means that floating-point math operations cannot generate a
(user-visible) trap. This is the case, for example, in nonstop
IEEE 754 arithmetic. */
@ -408,7 +431,7 @@ extern int flag_schedule_insns_after_reload;
/* The following flags have effect only for scheduling before register
allocation:
flag_schedule_interblock means schedule insns accross basic blocks.
flag_schedule_interblock means schedule insns across basic blocks.
flag_schedule_speculative means allow speculative motion of non-load insns.
flag_schedule_speculative_load means allow speculative motion of some
load insns.
@ -439,19 +462,13 @@ extern int flag_delayed_branch;
extern int flag_dump_unnumbered;
/* Nonzero means pretend it is OK to examine bits of target floats,
even if that isn't true. The resulting code will have incorrect constants,
but the same series of instructions that the native compiler would make. */
extern int flag_pretend_float;
/* Nonzero means change certain warnings into errors.
Usually these are warnings about failure to conform to some standard. */
extern int flag_pedantic_errors;
/* Nonzero means generate position-independent code.
This is not fully implemented yet. */
/* Nonzero means generate position-independent code. 1 vs 2 for a
target-dependent "small" or "large" mode. */
extern int flag_pic;
@ -546,19 +563,10 @@ extern int flag_peephole2;
/* Try to guess branch probablities. */
extern int flag_guess_branch_prob;
/* -fbounded-pointers causes gcc to compile pointers as composite
objects occupying three words: the pointer value, the base address
of the referent object, and the address immediately beyond the end
of the referent object. The base and extent allow us to perform
runtime bounds checking. -fbounded-pointers implies -fcheck-bounds. */
extern int flag_bounded_pointers;
/* -fcheck-bounds causes gcc to generate array bounds checks.
For C, C++: defaults to value of flag_bounded_pointers.
For ObjC: defaults to off.
For C, C++ and ObjC: defaults off.
For Java: defaults to on.
For Fortran: defaults to off.
For CHILL: defaults to off. */
For Fortran: defaults to off. */
extern int flag_bounds_check;
/* This will attempt to merge constant section constants, if 1 only
@ -638,11 +646,48 @@ extern int flag_gcse_sm;
extern int flag_eliminate_dwarf2_dups;
/* Non-zero means to collect statistics which might be expensive
/* Nonzero means to collect statistics which might be expensive
and to print them when we are done. */
extern int flag_detailed_statistics;
/* Nonzero means enable synchronous exceptions for non-call instructions. */
extern int flag_non_call_exceptions;
/* Nonzero means put zero initialized data in the bss section. */
extern int flag_zero_initialized_in_bss;
/* Nonzero means disable transformations observable by signaling NaNs. */
extern int flag_signaling_nans;
/* A string that's used when a random name is required. NULL means
to make it really random. */
extern const char *flag_random_seed;
/* True if the given mode has a NaN representation and the treatment of
NaN operands is important. Certain optimizations, such as folding
x * 0 into x, are not correct for NaN operands, and are normally
disabled for modes with NaNs. The user can ask for them to be
done anyway using the -funsafe-math-optimizations switch. */
#define HONOR_NANS(MODE) \
(MODE_HAS_NANS (MODE) && !flag_finite_math_only)
/* Like HONOR_NANs, but true if we honor signaling NaNs (or sNaNs). */
#define HONOR_SNANS(MODE) (flag_signaling_nans && HONOR_NANS (MODE))
/* As for HONOR_NANS, but true if the mode can represent infinity and
the treatment of infinite values is important. */
#define HONOR_INFINITIES(MODE) \
(MODE_HAS_INFINITIES (MODE) && !flag_finite_math_only)
/* Like HONOR_NANS, but true if the given mode distinguishes between
postive and negative zero, and the sign of zero is important. */
#define HONOR_SIGNED_ZEROS(MODE) \
(MODE_HAS_SIGNED_ZEROS (MODE) && !flag_unsafe_math_optimizations)
/* Like HONOR_NANS, but true if given mode supports sign-dependent rounding,
and the rounding mode is important. */
#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
(MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && !flag_unsafe_math_optimizations)
#endif /* ! GCC_FLAGS_H */

File diff suppressed because it is too large Load Diff

View File

@ -47,18 +47,13 @@ typedef __builtin_va_list __gnuc_va_list;
if this invocation was from the user program. */
#ifdef _STDARG_H
/* Note that the type used in va_arg is supposed to match the
actual type **after default promotions**.
Thus, va_arg (..., short) is not valid. */
#define va_start(v,l) __builtin_stdarg_start((v),l)
#define va_end __builtin_va_end
#define va_arg __builtin_va_arg
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L
#define va_copy(d,s) __builtin_va_copy((d),(s))
#define va_copy(d,s) __builtin_va_copy(d,s)
#endif
#define __va_copy(d,s) __builtin_va_copy((d),(s))
#define __va_copy(d,s) __builtin_va_copy(d,s)
/* Define va_list, if desired, from __gnuc_va_list. */
/* We deliberately do not define va_list when called from

View File

@ -1,144 +1,7 @@
/* Copyright (C) 1989, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
the resulting executable to be covered by the GNU General Public
License. This exception does not however invalidate any other
reasons why the executable file might be covered by the GNU General
Public License. */
#ifndef _VARARGS_H
#define _VARARGS_H
#ifdef __NeXT__
#error "GCC no longer implements <varargs.h>."
#error "Revise your code to use <stdarg.h>."
/* On Next, erase any vestiges of stdarg.h. */
#ifdef _ANSI_STDARG_H_
#define _VA_LIST_
#endif
#define _ANSI_STDARG_H_
#undef va_alist
#undef va_dcl
#undef va_list
#undef va_start
#undef va_end
#undef va_arg
#endif /* __NeXT__ */
/* These macros implement traditional (non-ANSI) varargs
for GNU C. */
#define va_alist __builtin_va_alist
/* ??? We don't process attributes correctly in K&R argument context. */
typedef int __builtin_va_alist_t __attribute__((__mode__(__word__)));
/* ??? It would be nice to get rid of the ellipsis here. It causes
current_function_varargs to be set in cc1. */
#define va_dcl __builtin_va_alist_t __builtin_va_alist; ...
/* Define __gnuc_va_list, just as in stdarg.h. */
#ifndef __GNUC_VA_LIST
#define __GNUC_VA_LIST
typedef __builtin_va_list __gnuc_va_list;
#endif
#define va_start(v) __builtin_varargs_start((v))
#define va_end __builtin_va_end
#define va_arg __builtin_va_arg
#define __va_copy(d,s) __builtin_va_copy((d),(s))
/* Define va_list from __gnuc_va_list. */
#ifdef _HIDDEN_VA_LIST /* On OSF1, this means varargs.h is "half-loaded". */
#undef _VA_LIST
#endif
#if defined(__svr4__) || (defined(_SCO_DS) && !defined(__VA_LIST))
/* SVR4.2 uses _VA_LIST for an internal alias for va_list,
so we must avoid testing it and setting it here.
SVR4 uses _VA_LIST as a flag in stdarg.h, but we should
have no conflict with that. */
#ifndef _VA_LIST_
#define _VA_LIST_
#ifdef __i860__
#ifndef _VA_LIST
#define _VA_LIST va_list
#endif
#endif /* __i860__ */
typedef __gnuc_va_list va_list;
#ifdef _SCO_DS
#define __VA_LIST
#endif
#endif /* _VA_LIST_ */
#else /* not __svr4__ || _SCO_DS */
/* The macro _VA_LIST_ is the same thing used by this file in Ultrix.
But on BSD NET2 we must not test or define or undef it.
(Note that the comments in NET 2's ansi.h
are incorrect for _VA_LIST_--see stdio.h!) */
/* Michael Eriksson <mer@sics.se> at Thu Sep 30 11:00:57 1993:
Sequent defines _VA_LIST_ in <machine/machtypes.h> to be the type to
use for va_list (``typedef _VA_LIST_ va_list'') */
#if !defined (_VA_LIST_) || defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__) || defined(WINNT)
/* The macro _VA_LIST_DEFINED is used in Windows NT 3.5 */
#ifndef _VA_LIST_DEFINED
/* The macro _VA_LIST is used in SCO Unix 3.2. */
#ifndef _VA_LIST
/* The macro _VA_LIST_T_H is used in the Bull dpx2 */
#ifndef _VA_LIST_T_H
/* The macro __va_list__ is used by BeOS. */
#ifndef __va_list__
typedef __gnuc_va_list va_list;
#endif /* not __va_list__ */
#endif /* not _VA_LIST_T_H */
#endif /* not _VA_LIST */
#endif /* not _VA_LIST_DEFINED */
#if !(defined (__BSD_NET2__) || defined (____386BSD____) || defined (__bsdi__) || defined (__sequent__) || defined (__FreeBSD__))
#define _VA_LIST_
#endif
#ifndef _VA_LIST
#define _VA_LIST
#endif
#ifndef _VA_LIST_DEFINED
#define _VA_LIST_DEFINED
#endif
#ifndef _VA_LIST_T_H
#define _VA_LIST_T_H
#endif
#ifndef __va_list__
#define __va_list__
#endif
#endif /* not _VA_LIST_, except on certain systems */
#endif /* not __svr4__ */
/* The next BSD release (if there is one) wants this symbol to be
undefined instead of _VA_LIST_. */
#ifdef _BSD_VA_LIST
#undef _BSD_VA_LIST
#endif
#endif /* _VARARGS_H */

View File

@ -43,10 +43,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "libgcc2.h"
#if defined (L_negdi2) || defined (L_divdi3) || defined (L_moddi3)
#if defined (L_divdi3) || defined (L_moddi3)
static inline
#ifdef DECLARE_LIBRARY_RENAMES
DECLARE_LIBRARY_RENAMES
#endif
#if defined (L_negdi2)
DWtype
__negdi2 (DWtype u)
{
@ -149,9 +150,9 @@ __mulvsi3 (Wtype a, Wtype b)
Wtype
__negvsi2 (Wtype a)
{
Wtype w;
Wtype w;
w = -a;
w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
@ -164,14 +165,14 @@ __negvsi2 (Wtype a)
DWtype
__negvdi2 (DWtype a)
{
DWtype w;
DWtype w;
w = -a;
w = -a;
if (a >= 0 ? w > 0 : w < 0)
abort ();
return w;
return w;
}
#endif
@ -179,16 +180,16 @@ __negvdi2 (DWtype a)
Wtype
__absvsi2 (Wtype a)
{
Wtype w = a;
Wtype w = a;
if (a < 0)
if (a < 0)
#ifdef L_negvsi2
w = __negvsi2 (a);
w = __negvsi2 (a);
#else
w = -a;
w = -a;
if (w < 0)
abort ();
if (w < 0)
abort ();
#endif
return w;
@ -199,19 +200,19 @@ __absvsi2 (Wtype a)
DWtype
__absvdi2 (DWtype a)
{
DWtype w = a;
DWtype w = a;
if (a < 0)
if (a < 0)
#ifdef L_negvsi2
w = __negvsi2 (a);
w = __negvsi2 (a);
#else
w = -a;
w = -a;
if (w < 0)
abort ();
if (w < 0)
abort ();
#endif
return w;
return w;
}
#endif
@ -219,7 +220,7 @@ __absvdi2 (DWtype a)
DWtype
__mulvdi3 (DWtype u, DWtype v)
{
DWtype w;
DWtype w;
w = u * v;
@ -365,8 +366,19 @@ __muldi3 (DWtype u, DWtype v)
}
#endif
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
#if defined (sdiv_qrnnd)
#define L_udiv_w_sdiv
#endif
#endif
#ifdef L_udiv_w_sdiv
#if defined (sdiv_qrnnd)
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
static inline __attribute__ ((__always_inline__))
#endif
UWtype
__udiv_w_sdiv (UWtype *rp, UWtype a1, UWtype a0, UWtype d)
{
@ -499,7 +511,7 @@ const UQItype __clz_tab[] =
#if (defined (L_udivdi3) || defined (L_divdi3) || \
defined (L_umoddi3) || defined (L_moddi3))
static inline
static inline __attribute__ ((__always_inline__))
#endif
UDWtype
__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
@ -732,14 +744,14 @@ __divdi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
uu.ll = __negdi2 (uu.ll);
uu.ll = -uu.ll;
if (vv.s.high < 0)
c = ~c,
vv.ll = __negdi2 (vv.ll);
vv.ll = -vv.ll;
w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
if (c)
w = __negdi2 (w);
w = -w;
return w;
}
@ -758,13 +770,13 @@ __moddi3 (DWtype u, DWtype v)
if (uu.s.high < 0)
c = ~c,
uu.ll = __negdi2 (uu.ll);
uu.ll = -uu.ll;
if (vv.s.high < 0)
vv.ll = __negdi2 (vv.ll);
vv.ll = -vv.ll;
(void) __udivmoddi4 (uu.ll, vv.ll, &w);
if (c)
w = __negdi2 (w);
w = -w;
return w;
}
@ -1063,35 +1075,10 @@ __floatdidf (DWtype u)
#define WORD_SIZE (sizeof (Wtype) * BITS_PER_UNIT)
#define HIGH_HALFWORD_COEFF (((UDWtype) 1) << (WORD_SIZE / 2))
#define HIGH_WORD_COEFF (((UDWtype) 1) << WORD_SIZE)
#define DI_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
/* Define codes for all the float formats that we know of. Note
that this is copied from real.h. */
#define UNKNOWN_FLOAT_FORMAT 0
#define IEEE_FLOAT_FORMAT 1
#define VAX_FLOAT_FORMAT 2
#define IBM_FLOAT_FORMAT 3
/* Default to IEEE float if not specified. Nearly all machines use it. */
#ifndef HOST_FLOAT_FORMAT
#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#if HOST_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#define DF_SIZE 53
#define SF_SIZE 24
#endif
#if HOST_FLOAT_FORMAT == IBM_FLOAT_FORMAT
#define DF_SIZE 56
#define SF_SIZE 24
#endif
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
#define DF_SIZE 56
#define SF_SIZE 24
#endif
#define DF_SIZE DBL_MANT_DIG
#define SF_SIZE FLT_MANT_DIG
SFtype
__floatdisf (DWtype u)
@ -1264,14 +1251,13 @@ __eprintf (const char *string, const char *expression,
#ifdef L_bb
#if LONG_TYPE_SIZE == GCOV_TYPE_SIZE
typedef long gcov_type;
#else
typedef long long gcov_type;
#endif
struct bb_function_info {
long checksum;
int arc_count;
const char *name;
};
/* Structure emitted by -a */
/* Structure emitted by --profile-arcs */
struct bb
{
long zero_word;
@ -1279,26 +1265,19 @@ struct bb
gcov_type *counts;
long ncounts;
struct bb *next;
const unsigned long *addresses;
/* Older GCC's did not emit these fields. */
long nwords;
const char **functions;
const long *line_nums;
const char **filenames;
char *flags;
long sizeof_bb;
struct bb_function_info *function_infos;
};
#ifndef inhibit_libc
/* Simple minded basic block profiling output dumper for
systems that don't provide tcov support. At present,
it requires atexit and stdio. */
/* Arc profile dumper. Requires atexit and stdio. */
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
#include "gbl-ctors.h"
#include "gcov-io.h"
#include <string.h>
#ifdef TARGET_HAS_F_SETLKW
@ -1306,162 +1285,272 @@ struct bb
#include <errno.h>
#endif
/* Chain of per-object file bb structures. */
static struct bb *bb_head;
/* Dump the coverage counts. We merge with existing counts when
possible, to avoid growing the .da files ad infinitum. */
void
__bb_exit_func (void)
{
FILE *da_file;
int i;
struct bb *ptr;
int i;
gcov_type program_sum = 0;
gcov_type program_max = 0;
long program_arcs = 0;
gcov_type merged_sum = 0;
gcov_type merged_max = 0;
long merged_arcs = 0;
#if defined (TARGET_HAS_F_SETLKW)
struct flock s_flock;
if (bb_head == 0)
return;
s_flock.l_type = F_WRLCK;
s_flock.l_whence = SEEK_SET;
s_flock.l_start = 0;
s_flock.l_len = 0; /* Until EOF. */
s_flock.l_pid = getpid ();
#endif
i = strlen (bb_head->filename) - 3;
for (ptr = bb_head; ptr != (struct bb *) 0; ptr = ptr->next)
/* Non-merged stats for this program. */
for (ptr = bb_head; ptr; ptr = ptr->next)
{
int firstchar;
for (i = 0; i < ptr->ncounts; i++)
{
program_sum += ptr->counts[i];
/* Make sure the output file exists -
but don't clobber exiting data. */
if ((da_file = fopen (ptr->filename, "a")) != 0)
fclose (da_file);
/* Need to re-open in order to be able to write from the start. */
if (ptr->counts[i] > program_max)
program_max = ptr->counts[i];
}
program_arcs += ptr->ncounts;
}
for (ptr = bb_head; ptr; ptr = ptr->next)
{
FILE *da_file;
gcov_type object_max = 0;
gcov_type object_sum = 0;
long object_functions = 0;
int merging = 0;
int error = 0;
struct bb_function_info *fn_info;
gcov_type *count_ptr;
/* Open for modification */
da_file = fopen (ptr->filename, "r+b");
/* Some old systems might not allow the 'b' mode modifier.
Therefore, try to open without it. This can lead to a race
condition so that when you delete and re-create the file, the
file might be opened in text mode, but then, you shouldn't
delete the file in the first place. */
if (da_file == 0)
da_file = fopen (ptr->filename, "r+");
if (da_file == 0)
if (da_file)
merging = 1;
else
{
/* Try for appending */
da_file = fopen (ptr->filename, "ab");
/* Some old systems might not allow the 'b' mode modifier.
Therefore, try to open without it. This can lead to a
race condition so that when you delete and re-create the
file, the file might be opened in text mode, but then,
you shouldn't delete the file in the first place. */
if (!da_file)
da_file = fopen (ptr->filename, "a");
}
if (!da_file)
{
fprintf (stderr, "arc profiling: Can't open output file %s.\n",
ptr->filename);
ptr->filename = 0;
continue;
}
#if defined (TARGET_HAS_F_SETLKW)
/* After a fork, another process might try to read and/or write
the same file simultanously. So if we can, lock the file to
avoid race conditions. */
#if defined (TARGET_HAS_F_SETLKW)
{
struct flock s_flock;
s_flock.l_type = F_WRLCK;
s_flock.l_whence = SEEK_SET;
s_flock.l_start = 0;
s_flock.l_len = 1;
s_flock.l_pid = getpid ();
while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
&& errno == EINTR);
}
while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
#endif
for (fn_info = ptr->function_infos; fn_info->arc_count != -1; fn_info++)
object_functions++;
/* If the file is not empty, and the number of counts in it is the
same, then merge them in. */
firstchar = fgetc (da_file);
if (firstchar == EOF)
if (merging)
{
if (ferror (da_file))
/* Merge data from file. */
long tmp_long;
gcov_type tmp_gcov;
if (/* magic */
(__read_long (&tmp_long, da_file, 4) || tmp_long != -123l)
/* functions in object file. */
|| (__read_long (&tmp_long, da_file, 4)
|| tmp_long != object_functions)
/* extension block, skipped */
|| (__read_long (&tmp_long, da_file, 4)
|| fseek (da_file, tmp_long, SEEK_CUR)))
{
fprintf (stderr, "arc profiling: Can't read output file ");
perror (ptr->filename);
}
}
else
{
long n_counts = 0;
if (ungetc (firstchar, da_file) == EOF)
rewind (da_file);
if (__read_long (&n_counts, da_file, 8) != 0)
{
fprintf (stderr, "arc profiling: Can't read output file %s.\n",
read_error:;
fprintf (stderr, "arc profiling: Error merging output file %s.\n",
ptr->filename);
continue;
clearerr (da_file);
}
if (n_counts == ptr->ncounts)
else
{
int i;
for (i = 0; i < n_counts; i++)
/* Merge execution counts for each function. */
count_ptr = ptr->counts;
for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
fn_info++)
{
gcov_type v = 0;
if (/* function name delim */
(__read_long (&tmp_long, da_file, 4)
|| tmp_long != -1)
/* function name length */
|| (__read_long (&tmp_long, da_file, 4)
|| tmp_long != (long) strlen (fn_info->name))
/* skip string */
|| fseek (da_file, ((tmp_long + 1) + 3) & ~3, SEEK_CUR)
/* function name delim */
|| (__read_long (&tmp_long, da_file, 4)
|| tmp_long != -1))
goto read_error;
if (__read_gcov_type (&v, da_file, 8) != 0)
{
fprintf (stderr,
"arc profiling: Can't read output file %s.\n",
ptr->filename);
break;
}
ptr->counts[i] += v;
if (/* function checksum */
(__read_long (&tmp_long, da_file, 4)
|| tmp_long != fn_info->checksum)
/* arc count */
|| (__read_long (&tmp_long, da_file, 4)
|| tmp_long != fn_info->arc_count))
goto read_error;
for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
if (__read_gcov_type (&tmp_gcov, da_file, 8))
goto read_error;
else
*count_ptr += tmp_gcov;
}
}
fseek (da_file, 0, SEEK_SET);
}
rewind (da_file);
/* ??? Should first write a header to the file. Preferably, a 4 byte
magic number, 4 bytes containing the time the program was
compiled, 4 bytes containing the last modification time of the
source file, and 4 bytes indicating the compiler options used.
That way we can easily verify that the proper source/executable/
data file combination is being used from gcov. */
if (__write_gcov_type (ptr->ncounts, da_file, 8) != 0)
/* Calculate the per-object statistics. */
for (i = 0; i < ptr->ncounts; i++)
{
object_sum += ptr->counts[i];
if (ptr->counts[i] > object_max)
object_max = ptr->counts[i];
}
merged_sum += object_sum;
if (merged_max < object_max)
merged_max = object_max;
merged_arcs += ptr->ncounts;
/* Write out the data. */
if (/* magic */
__write_long (-123, da_file, 4)
/* number of functions in object file. */
|| __write_long (object_functions, da_file, 4)
/* length of extra data in bytes. */
|| __write_long ((4 + 8 + 8) + (4 + 8 + 8), da_file, 4)
/* whole program statistics. If merging write per-object
now, rewrite later */
/* number of instrumented arcs. */
|| __write_long (merging ? ptr->ncounts : program_arcs, da_file, 4)
/* sum of counters. */
|| __write_gcov_type (merging ? object_sum : program_sum, da_file, 8)
/* maximal counter. */
|| __write_gcov_type (merging ? object_max : program_max, da_file, 8)
/* per-object statistics. */
/* number of counters. */
|| __write_long (ptr->ncounts, da_file, 4)
/* sum of counters. */
|| __write_gcov_type (object_sum, da_file, 8)
/* maximal counter. */
|| __write_gcov_type (object_max, da_file, 8))
{
write_error:;
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
error = 1;
}
else
{
int j;
gcov_type *count_ptr = ptr->counts;
int ret = 0;
for (j = ptr->ncounts; j > 0; j--)
/* Write execution counts for each function. */
count_ptr = ptr->counts;
for (fn_info = ptr->function_infos; fn_info->arc_count != -1;
fn_info++)
{
if (__write_gcov_type (*count_ptr, da_file, 8) != 0)
{
ret = 1;
break;
}
count_ptr++;
if (__write_gcov_string (fn_info->name,
strlen (fn_info->name), da_file, -1)
|| __write_long (fn_info->checksum, da_file, 4)
|| __write_long (fn_info->arc_count, da_file, 4))
goto write_error;
for (i = fn_info->arc_count; i > 0; i--, count_ptr++)
if (__write_gcov_type (*count_ptr, da_file, 8))
goto write_error; /* RIP Edsger Dijkstra */
}
if (ret)
fprintf (stderr, "arc profiling: Error writing output file %s.\n",
ptr->filename);
}
if (fclose (da_file) == EOF)
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
if (fclose (da_file))
{
fprintf (stderr, "arc profiling: Error closing output file %s.\n",
ptr->filename);
error = 1;
}
if (error || !merging)
ptr->filename = 0;
}
return;
/* Upate whole program statistics. */
for (ptr = bb_head; ptr; ptr = ptr->next)
if (ptr->filename)
{
FILE *da_file;
da_file = fopen (ptr->filename, "r+b");
if (!da_file)
{
fprintf (stderr, "arc profiling: Cannot reopen %s.\n",
ptr->filename);
continue;
}
#if defined (TARGET_HAS_F_SETLKW)
while (fcntl (fileno (da_file), F_SETLKW, &s_flock)
&& errno == EINTR)
continue;
#endif
if (fseek (da_file, 4 * 3, SEEK_SET)
/* number of instrumented arcs. */
|| __write_long (merged_arcs, da_file, 4)
/* sum of counters. */
|| __write_gcov_type (merged_sum, da_file, 8)
/* maximal counter. */
|| __write_gcov_type (merged_max, da_file, 8))
fprintf (stderr, "arc profiling: Error updating program header %s.\n",
ptr->filename);
if (fclose (da_file))
fprintf (stderr, "arc profiling: Error reclosing %s\n",
ptr->filename);
}
}
/* Add a new object file onto the bb chain. Invoked automatically
when running an object file's global ctors. */
void
__bb_init_func (struct bb *blocks)
{
/* User is supposed to check whether the first word is non-0,
but just in case.... */
if (blocks->zero_word)
return;
/* Initialize destructor. */
/* Initialize destructor and per-thread data. */
if (!bb_head)
atexit (__bb_exit_func);
@ -1474,6 +1563,7 @@ __bb_init_func (struct bb *blocks)
/* Called before fork or exec - write out profile information gathered so
far and reset it to zero. This avoids duplication or loss of the
profile information gathered so far. */
void
__bb_fork_func (void)
{
@ -1656,102 +1746,6 @@ mprotect (char *addr, int len, int prot)
TRANSFER_FROM_TRAMPOLINE
#endif
#if defined (NeXT) && defined (__MACH__)
/* Make stack executable so we can call trampolines on stack.
This is called from INITIALIZE_TRAMPOLINE in next.h. */
#ifdef NeXTStep21
#include <mach.h>
#else
#include <mach/mach.h>
#endif
void
__enable_execute_stack (char *addr)
{
kern_return_t r;
char *eaddr = addr + TRAMPOLINE_SIZE;
vm_address_t a = (vm_address_t) addr;
/* turn on execute access on stack */
r = vm_protect (task_self (), a, TRAMPOLINE_SIZE, FALSE, VM_PROT_ALL);
if (r != KERN_SUCCESS)
{
mach_error("vm_protect VM_PROT_ALL", r);
exit(1);
}
/* We inline the i-cache invalidation for speed */
#ifdef CLEAR_INSN_CACHE
CLEAR_INSN_CACHE (addr, eaddr);
#else
__clear_cache ((int) addr, (int) eaddr);
#endif
}
#endif /* defined (NeXT) && defined (__MACH__) */
#ifdef __convex__
/* Make stack executable so we can call trampolines on stack.
This is called from INITIALIZE_TRAMPOLINE in convex.h. */
#include <sys/mman.h>
#include <sys/vmparam.h>
#include <machine/machparam.h>
void
__enable_execute_stack (void)
{
int fp;
static unsigned lowest = USRSTACK;
unsigned current = (unsigned) &fp & -NBPG;
if (lowest > current)
{
unsigned len = lowest - current;
mremap (current, &len, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE);
lowest = current;
}
/* Clear instruction cache in case an old trampoline is in it. */
asm ("pich");
}
#endif /* __convex__ */
#ifdef __sysV88__
/* Modified from the convex -code above. */
#include <sys/param.h>
#include <errno.h>
#include <sys/m88kbcs.h>
void
__enable_execute_stack (void)
{
int save_errno;
static unsigned long lowest = USRSTACK;
unsigned long current = (unsigned long) &save_errno & -NBPC;
/* Ignore errno being set. memctl sets errno to EINVAL whenever the
address is seen as 'negative'. That is the case with the stack. */
save_errno=errno;
if (lowest > current)
{
unsigned len=lowest-current;
memctl(current,len,MCT_TEXT);
lowest = current;
}
else
memctl(current,NBPC,MCT_TEXT);
errno=save_errno;
}
#endif /* __sysV88__ */
#ifdef __sysV68__
#include <sys/signal.h>
@ -1796,57 +1790,6 @@ __clear_insn_cache (void)
}
#endif /* __sysV68__ */
#ifdef __pyr__
#undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/vmmac.h>
/* Modified from the convex -code above.
mremap promises to clear the i-cache. */
void
__enable_execute_stack (void)
{
int fp;
if (mprotect (((unsigned int)&fp/PAGSIZ)*PAGSIZ, PAGSIZ,
PROT_READ|PROT_WRITE|PROT_EXEC))
{
perror ("mprotect in __enable_execute_stack");
fflush (stderr);
abort ();
}
}
#endif /* __pyr__ */
#if defined (sony_news) && defined (SYSTYPE_BSD)
#include <stdio.h>
#include <sys/types.h>
#include <sys/param.h>
#include <syscall.h>
#include <machine/sysnews.h>
/* cacheflush function for NEWS-OS 4.2.
This function is called from trampoline-initialize code
defined in config/mips/mips.h. */
void
cacheflush (char *beg, int size, int flag)
{
if (syscall (SYS_sysnews, NEWS_CACHEFLUSH, beg, size, FLUSH_BCACHE))
{
perror ("cache_flush");
fflush (stderr);
abort ();
}
}
#endif /* sony_news */
#endif /* L_trampoline */
#ifndef __CYGWIN__

View File

@ -23,6 +23,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "config.h"
#include "system.h"
#include "tree.h"
#include "real.h"
#include "ggc.h"
#include "langhooks.h"
@ -47,8 +48,7 @@ void
debug_tree (node)
tree node;
{
table = (struct bucket **) permalloc (HASH_SIZE * sizeof (struct bucket *));
memset ((char *) table, 0, HASH_SIZE * sizeof (struct bucket *));
table = (struct bucket **) xcalloc (HASH_SIZE, sizeof (struct bucket *));
print_node (stderr, "", node, 0);
table = 0;
fprintf (stderr, "\n");
@ -124,7 +124,6 @@ print_node_brief (file, prefix, node, indent)
if (TREE_OVERFLOW (node))
fprintf (file, " overflow");
#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
@ -132,21 +131,10 @@ print_node_brief (file, prefix, node, indent)
fprintf (file, " Nan");
else
{
char string[100];
REAL_VALUE_TO_DECIMAL (d, "%e", string);
char string[60];
real_to_decimal (string, &d, sizeof (string), 0, 1);
fprintf (file, " %s", string);
}
#else
{
int i;
unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
fprintf (file, " 0x");
for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
fprintf (file, "%02x", *p++);
fprintf (file, "");
}
#endif
}
fprintf (file, ">");
@ -223,7 +211,7 @@ print_node (file, prefix, node, indent)
}
/* Add this node to the table. */
b = (struct bucket *) permalloc (sizeof (struct bucket));
b = (struct bucket *) xmalloc (sizeof (struct bucket));
b->node = node;
b->next = table[hash];
table[hash] = b;
@ -340,7 +328,9 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" suppress-debug", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node))
fputs (" autoinline", file);
else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (" inline", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
fputs (" built-in", file);
@ -363,6 +353,8 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == VAR_DECL && DECL_IN_TEXT_SECTION (node))
fputs (" in-text-section", file);
if (TREE_CODE (node) == VAR_DECL && DECL_THREAD_LOCAL (node))
fputs (" thread-local", file);
if (TREE_CODE (node) == PARM_DECL && DECL_TRANSPARENT_UNION (node))
fputs (" transparent-union", file);
@ -395,7 +387,7 @@ print_node (file, prefix, node, indent)
print_node (file, "size", DECL_SIZE (node), indent + 4);
print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4);
if (TREE_CODE (node) != FUNCTION_DECL
|| DECL_INLINE (node) || DECL_BUILT_IN (node))
indent_to (file, indent + 3);
@ -426,7 +418,7 @@ print_node (file, prefix, node, indent)
if (DECL_POINTER_ALIAS_SET_KNOWN_P (node))
{
fprintf (file, " alias set ");
fprintf (file, HOST_WIDE_INT_PRINT_DEC,
fprintf (file, HOST_WIDE_INT_PRINT_DEC,
DECL_POINTER_ALIAS_SET (node));
}
@ -517,6 +509,9 @@ print_node (file, prefix, node, indent)
if (TYPE_PACKED (node))
fputs (" packed", file);
if (TYPE_RESTRICT (node))
fputs (" restrict", file);
if (TYPE_LANG_FLAG_0 (node))
fputs (" type_0", file);
if (TYPE_LANG_FLAG_1 (node))
@ -644,7 +639,7 @@ print_node (file, prefix, node, indent)
if (TREE_CODE (node) == EXPR_WITH_FILE_LOCATION)
{
indent_to (file, indent+4);
fprintf (file, "%s:%d:%d",
fprintf (file, "%s:%d:%d",
(EXPR_WFL_FILENAME_NODE (node ) ?
EXPR_WFL_FILENAME (node) : "(no file info)"),
EXPR_WFL_LINENO (node), EXPR_WFL_COLNO (node));
@ -683,7 +678,6 @@ print_node (file, prefix, node, indent)
if (TREE_OVERFLOW (node))
fprintf (file, " overflow");
#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
d = TREE_REAL_CST (node);
if (REAL_VALUE_ISINF (d))
fprintf (file, " Inf");
@ -691,21 +685,10 @@ print_node (file, prefix, node, indent)
fprintf (file, " Nan");
else
{
char string[100];
REAL_VALUE_TO_DECIMAL (d, "%e", string);
char string[64];
real_to_decimal (string, &d, sizeof (string), 0, 1);
fprintf (file, " %s", string);
}
#else
{
int i;
unsigned char *p = (unsigned char *) &TREE_REAL_CST (node);
fprintf (file, " 0x");
for (i = 0; i < sizeof TREE_REAL_CST (node); i++)
fprintf (file, "%02x", *p++);
fprintf (file, "");
}
#endif
}
break;
@ -731,7 +714,20 @@ print_node (file, prefix, node, indent)
break;
case STRING_CST:
fprintf (file, " \"%s\"", TREE_STRING_POINTER (node));
{
const char *p = TREE_STRING_POINTER (node);
int i = TREE_STRING_LENGTH (node);
fputs (" \"", file);
while (--i >= 0)
{
char ch = *p++;
if (ch >= ' ' && ch < 127)
putc (ch, file);
else
fprintf(file, "\\%03o", ch & 0xFF);
}
fputc ('\"', file);
}
/* Print the chain at second level. */
if (indent == 4)
print_node (file, "chain", TREE_CHAIN (node), indent + 4);

View File

@ -161,7 +161,7 @@ check_asm_operands (x)
c = constraints[c[0] - '0'];
if (! asm_operand_ok (operands[i], c))
return 0;
return 0;
}
return 1;
@ -191,7 +191,7 @@ static int num_changes = 0;
an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
the change in place.
IN_GROUP is non-zero if this is part of a group of changes that must be
IN_GROUP is nonzero if this is part of a group of changes that must be
performed as a group. In that case, the changes will be stored. The
function `apply_change_group' will validate and apply the changes.
@ -227,11 +227,11 @@ validate_change (object, loc, new, in_group)
else
changes_allocated *= 2;
changes =
(change_t*) xrealloc (changes,
sizeof (change_t) * changes_allocated);
changes =
(change_t*) xrealloc (changes,
sizeof (change_t) * changes_allocated);
}
changes[num_changes].object = object;
changes[num_changes].loc = loc;
changes[num_changes].old = old;
@ -272,7 +272,7 @@ insn_invalid_p (insn)
? &num_clobbers : 0);
int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
/* If this is an asm and the operand aren't legal, then fail. Likewise if
this is not an asm and the insn wasn't recognized. */
if ((is_asm && ! check_asm_operands (PATTERN (insn)))
@ -308,6 +308,13 @@ insn_invalid_p (insn)
return 0;
}
/* Return number of changes made and not validated yet. */
int
num_changes_pending ()
{
return num_changes;
}
/* Apply a group of changes previously issued with `validate_change'.
Return 1 if all changes are valid, zero otherwise. */
@ -362,7 +369,7 @@ apply_change_group ()
int j;
newpat
= gen_rtx_PARALLEL (VOIDmode,
= gen_rtx_PARALLEL (VOIDmode,
rtvec_alloc (XVECLEN (pat, 0) - 1));
for (j = 0; j < XVECLEN (newpat, 0); j++)
XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
@ -392,6 +399,14 @@ apply_change_group ()
if (i == num_changes)
{
basic_block bb;
for (i = 0; i < num_changes; i++)
if (changes[i].object
&& INSN_P (changes[i].object)
&& (bb = BLOCK_FOR_INSN (changes[i].object)))
bb->flags |= BB_DIRTY;
num_changes = 0;
return 1;
}
@ -663,11 +678,10 @@ validate_replace_src_1 (x, data)
}
/* Try replacing every occurrence of FROM in INSN with TO, avoiding
SET_DESTs. After all changes have been made, validate by seeing if
INSN is still valid. */
SET_DESTs. */
int
validate_replace_src (from, to, insn)
void
validate_replace_src_group (from, to, insn)
rtx from, to, insn;
{
struct validate_replace_src_data d;
@ -676,6 +690,15 @@ validate_replace_src (from, to, insn)
d.to = to;
d.insn = insn;
note_uses (&PATTERN (insn), validate_replace_src_1, &d);
}
/* Same as validate_repalace_src_group, but validate by seeing if
INSN is still valid. */
int
validate_replace_src (from, to, insn)
rtx from, to, insn;
{
validate_replace_src_group (from, to, insn);
return apply_change_group ();
}
@ -778,7 +801,7 @@ find_single_use_1 (dest, loc)
case MEM:
case SUBREG:
return find_single_use_1 (dest, &XEXP (x, 0));
default:
break;
}
@ -833,7 +856,7 @@ find_single_use_1 (dest, loc)
sequel. If so, return a pointer to the innermost rtx expression in which
it is used.
If PLOC is non-zero, *PLOC is set to the insn containing the single use.
If PLOC is nonzero, *PLOC is set to the insn containing the single use.
This routine will return usually zero either before flow is called (because
there will be no LOG_LINKS notes) or after reload (because the REG_DEAD
@ -931,6 +954,7 @@ general_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@ -962,15 +986,15 @@ general_operand (op, mode)
/* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
may result in incorrect reference. We should simplify all valid
subregs of MEM anyway. But allow this after reload because we
might be called from cleanup_subreg_operands.
might be called from cleanup_subreg_operands.
??? This is a kludge. */
if (!reload_completed && SUBREG_BYTE (op) != 0
&& GET_CODE (sub) == MEM)
return 0;
return 0;
/* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
create such rtl, and we must reject it. */
create such rtl, and we must reject it. */
if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
&& GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
return 0;
@ -1059,13 +1083,10 @@ register_operand (op, mode)
if (! reload_completed && GET_CODE (sub) == MEM)
return general_operand (op, mode);
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
if (GET_CODE (sub) == REG
&& REGNO (sub) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (sub)))
&& CLASS_CANNOT_CHANGE_MODE_P (mode, GET_MODE (sub))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
&& GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT)
return 0;
@ -1136,6 +1157,7 @@ immediate_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@ -1218,6 +1240,7 @@ nonmemory_operand (op, mode)
return 0;
if (GET_CODE (op) == CONST_INT
&& mode != VOIDmode
&& trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
return 0;
@ -1334,7 +1357,7 @@ memory_address_p (mode, addr)
{
if (GET_CODE (addr) == ADDRESSOF)
return 1;
GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
return 0;
@ -1588,7 +1611,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
{
if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
break; /* Past last SET */
if (operands)
operands[i] = SET_DEST (XVECEXP (body, 0, i));
if (operand_locs)
@ -1640,7 +1663,7 @@ decode_asm_operands (body, operands, operand_locs, constraints, modes)
return template;
}
/* Check if an asm_operand matches it's constraints.
/* Check if an asm_operand matches it's constraints.
Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
int
@ -1708,7 +1731,7 @@ asm_operand_ok (op, constraint)
if (GET_CODE (op) == MEM
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_DEC
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
|| GET_CODE (XEXP (op, 0)) == POST_DEC))
return 1;
break;
@ -1716,23 +1739,15 @@ asm_operand_ok (op, constraint)
if (GET_CODE (op) == MEM
&& (1
|| GET_CODE (XEXP (op, 0)) == PRE_INC
|| GET_CODE (XEXP (op, 0)) == POST_INC))
|| GET_CODE (XEXP (op, 0)) == POST_INC))
return 1;
break;
case 'E':
#ifndef REAL_ARITHMETIC
/* Match any floating double constant, but only if
we can examine the bits of it reliably. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& GET_MODE (op) != VOIDmode && ! flag_pretend_float)
break;
#endif
/* FALLTHRU */
case 'F':
if (GET_CODE (op) == CONST_DOUBLE)
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
return 1;
break;
@ -1833,6 +1848,18 @@ asm_operand_ok (op, constraint)
#ifdef EXTRA_CONSTRAINT
if (EXTRA_CONSTRAINT (op, c))
return 1;
if (EXTRA_MEMORY_CONSTRAINT (c))
{
/* Every memory operand can be reloaded to fit. */
if (memory_operand (op, VOIDmode))
return 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
{
/* Every address operand can be reloaded to fit. */
if (address_operand (op, VOIDmode))
return 1;
}
#endif
break;
}
@ -2230,7 +2257,7 @@ preprocess_constraints ()
break;
case '&':
op_alt[j].earlyclobber = 1;
break;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
@ -2272,6 +2299,19 @@ preprocess_constraints ()
break;
default:
if (EXTRA_MEMORY_CONSTRAINT (c))
{
op_alt[j].memory_ok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
{
op_alt[j].is_address = 1;
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class]
[(int) MODE_BASE_REG_CLASS (VOIDmode)];
break;
}
op_alt[j].class = reg_class_subunion[(int) op_alt[j].class][(int) REG_CLASS_FROM_LETTER ((unsigned char) c)];
break;
}
@ -2279,7 +2319,7 @@ preprocess_constraints ()
}
}
}
/* Check the operands of an insn against the insn's operand constraints
and return 1 if they are valid.
The information about the insn's operands, constraints, operand modes
@ -2298,7 +2338,7 @@ preprocess_constraints ()
This is used in final, just before printing the assembler code and by
the routines that determine an insn's attribute.
If STRICT is a positive non-zero value, it means that we have been
If STRICT is a positive nonzero value, it means that we have been
called after reload has been completed. In that case, we must
do all checks strictly. If it is zero, it means that we have been called
before reload has completed. In that case, we first try to see if we can
@ -2499,20 +2539,10 @@ constrain_operands (strict)
break;
case 'E':
#ifndef REAL_ARITHMETIC
/* Match any CONST_DOUBLE, but only if
we can examine the bits of it reliably. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& GET_MODE (op) != VOIDmode && ! flag_pretend_float)
break;
#endif
if (GET_CODE (op) == CONST_DOUBLE)
win = 1;
break;
case 'F':
if (GET_CODE (op) == CONST_DOUBLE)
if (GET_CODE (op) == CONST_DOUBLE
|| (GET_CODE (op) == CONST_VECTOR
&& GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT))
win = 1;
break;
@ -2595,6 +2625,28 @@ constrain_operands (strict)
#ifdef EXTRA_CONSTRAINT
else if (EXTRA_CONSTRAINT (op, c))
win = 1;
if (EXTRA_MEMORY_CONSTRAINT (c))
{
/* Every memory operand can be reloaded to fit. */
if (strict < 0 && GET_CODE (op) == MEM)
win = 1;
/* Before reload, accept what reload can turn into mem. */
if (strict < 0 && CONSTANT_P (op))
win = 1;
/* During reload, accept a pseudo */
if (reload_in_progress && GET_CODE (op) == REG
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)
win = 1;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
{
/* Every address operand can be reloaded to fit. */
if (strict < 0)
win = 1;
}
#endif
break;
}
@ -2711,11 +2763,7 @@ split_insn (insn)
allocation, and there are unlikely to be very many
nops then anyways. */
if (reload_completed)
{
PUT_CODE (insn, NOTE);
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;
}
delete_insn_and_edges (insn);
}
else
{
@ -2731,7 +2779,7 @@ split_insn (insn)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
/* ??? Coddle to md files that generate subregs in post-
reload splitters instead of computing the proper
reload splitters instead of computing the proper
hard register. */
if (reload_completed && first != last)
{
@ -2757,25 +2805,26 @@ split_all_insns (upd_life)
int upd_life;
{
sbitmap blocks;
int changed;
int i;
bool changed;
basic_block bb;
blocks = sbitmap_alloc (n_basic_blocks);
blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
changed = 0;
changed = false;
for (i = n_basic_blocks - 1; i >= 0; --i)
FOR_EACH_BB_REVERSE (bb)
{
basic_block bb = BASIC_BLOCK (i);
rtx insn, next;
bool finish = false;
for (insn = bb->head; insn ; insn = next)
for (insn = bb->head; !finish ; insn = next)
{
rtx last;
/* Can't use `next_real_insn' because that might go across
CODE_LABELS and short-out basic blocks. */
next = NEXT_INSN (insn);
finish = (insn == bb->end);
last = split_insn (insn);
if (last)
{
@ -2785,29 +2834,27 @@ split_all_insns (upd_life)
while (GET_CODE (last) == BARRIER)
last = PREV_INSN (last);
SET_BIT (blocks, i);
changed = 1;
SET_BIT (blocks, bb->index);
changed = true;
insn = last;
}
if (insn == bb->end)
break;
}
if (insn == NULL)
abort ();
}
if (changed)
{
int old_last_basic_block = last_basic_block;
find_many_sub_basic_blocks (blocks);
if (old_last_basic_block != last_basic_block && upd_life)
blocks = sbitmap_resize (blocks, last_basic_block, 1);
}
if (changed && upd_life)
{
count_or_remove_death_notes (blocks, 1);
update_life_info (blocks, UPDATE_LIFE_LOCAL, PROP_DEATH_NOTES);
}
update_life_info (blocks, UPDATE_LIFE_GLOBAL_RM_NOTES,
PROP_DEATH_NOTES | PROP_REG_INFO);
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
@ -2815,7 +2862,7 @@ split_all_insns (upd_life)
sbitmap_free (blocks);
}
/* Same as split_all_insns, but do not expect CFG to be available.
/* Same as split_all_insns, but do not expect CFG to be available.
Used by machine depedent reorg passes. */
void
@ -3034,7 +3081,8 @@ peephole2_optimize (dump_file)
regset_head rs_heads[MAX_INSNS_PER_PEEP2 + 2];
rtx insn, prev;
regset live;
int i, b;
int i;
basic_block bb;
#ifdef HAVE_conditional_execution
sbitmap blocks;
bool changed;
@ -3048,16 +3096,15 @@ peephole2_optimize (dump_file)
live = INITIALIZE_REG_SET (rs_heads[i]);
#ifdef HAVE_conditional_execution
blocks = sbitmap_alloc (n_basic_blocks);
blocks = sbitmap_alloc (last_basic_block);
sbitmap_zero (blocks);
changed = false;
#else
count_or_remove_death_notes (NULL, 1);
#endif
for (b = n_basic_blocks - 1; b >= 0; --b)
FOR_EACH_BB_REVERSE (bb)
{
basic_block bb = BASIC_BLOCK (b);
struct propagate_block_info *pbi;
/* Indicate that all slots except the last holds invalid data. */
@ -3086,6 +3133,7 @@ peephole2_optimize (dump_file)
rtx try, before_try, x;
int match_len;
rtx note;
bool was_call = false;
/* Record this insn. */
if (--peep2_current < 0)
@ -3103,7 +3151,7 @@ peephole2_optimize (dump_file)
cfg-related call notes. */
for (i = 0; i <= match_len; ++i)
{
int j, k;
int j;
rtx old_insn, new_insn, note;
j = i + peep2_current;
@ -3112,21 +3160,17 @@ peephole2_optimize (dump_file)
old_insn = peep2_insn_data[j].insn;
if (GET_CODE (old_insn) != CALL_INSN)
continue;
was_call = true;
new_insn = NULL_RTX;
if (GET_CODE (try) == SEQUENCE)
for (k = XVECLEN (try, 0) - 1; k >= 0; k--)
{
rtx x = XVECEXP (try, 0, k);
if (GET_CODE (x) == CALL_INSN)
{
new_insn = x;
break;
}
}
else if (GET_CODE (try) == CALL_INSN)
new_insn = try;
if (! new_insn)
new_insn = try;
while (new_insn != NULL_RTX)
{
if (GET_CODE (new_insn) == CALL_INSN)
break;
new_insn = NEXT_INSN (new_insn);
}
if (new_insn == NULL_RTX)
abort ();
CALL_INSN_FUNCTION_USAGE (new_insn)
@ -3166,22 +3210,23 @@ peephole2_optimize (dump_file)
if (i >= MAX_INSNS_PER_PEEP2 + 1)
i -= MAX_INSNS_PER_PEEP2 + 1;
note = find_reg_note (peep2_insn_data[i].insn,
note = find_reg_note (peep2_insn_data[i].insn,
REG_EH_REGION, NULL_RTX);
/* Replace the old sequence with the new. */
try = emit_insn_after (try, peep2_insn_data[i].insn);
try = emit_insn_after_scope (try, peep2_insn_data[i].insn,
INSN_SCOPE (peep2_insn_data[i].insn));
before_try = PREV_INSN (insn);
delete_insn_chain (insn, peep2_insn_data[i].insn);
/* Re-insert the EH_REGION notes. */
if (note)
if (note || (was_call && nonlocal_goto_handler_labels))
{
edge eh_edge;
for (eh_edge = bb->succ; eh_edge
; eh_edge = eh_edge->succ_next)
if (eh_edge->flags & EDGE_EH)
if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
break;
for (x = try ; x != before_try ; x = PREV_INSN (x))
@ -3190,10 +3235,11 @@ peephole2_optimize (dump_file)
&& may_trap_p (PATTERN (x))
&& !find_reg_note (x, REG_EH_REGION, NULL)))
{
REG_NOTES (x)
= gen_rtx_EXPR_LIST (REG_EH_REGION,
XEXP (note, 0),
REG_NOTES (x));
if (note)
REG_NOTES (x)
= gen_rtx_EXPR_LIST (REG_EH_REGION,
XEXP (note, 0),
REG_NOTES (x));
if (x != bb->end && eh_edge)
{
@ -3201,7 +3247,8 @@ peephole2_optimize (dump_file)
int flags;
nfte = split_block (bb, x);
flags = EDGE_EH | EDGE_ABNORMAL;
flags = (eh_edge->flags
& (EDGE_EH | EDGE_ABNORMAL));
if (GET_CODE (x) == CALL_INSN)
flags |= EDGE_ABNORMAL_CALL;
nehe = make_edge (nfte->src, eh_edge->dest,
@ -3232,7 +3279,7 @@ peephole2_optimize (dump_file)
death data structures are not so self-contained.
So record that we've made a modification to this
block and update life information at the end. */
SET_BIT (blocks, b);
SET_BIT (blocks, bb->index);
changed = true;
for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
@ -3310,3 +3357,114 @@ peephole2_optimize (dump_file)
#endif
}
#endif /* HAVE_peephole2 */
/* Common predicates for use with define_bypass. */
/* True if the dependency between OUT_INSN and IN_INSN is on the store
data not the address operand(s) of the store. IN_INSN must be
single_set. OUT_INSN must be either a single_set or a PARALLEL with
SETs inside. */
int
store_data_bypass_p (out_insn, in_insn)
rtx out_insn, in_insn;
{
rtx out_set, in_set;
in_set = single_set (in_insn);
if (! in_set)
abort ();
if (GET_CODE (SET_DEST (in_set)) != MEM)
return false;
out_set = single_set (out_insn);
if (out_set)
{
if (reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set)))
return false;
}
else
{
rtx out_pat;
int i;
out_pat = PATTERN (out_insn);
if (GET_CODE (out_pat) != PARALLEL)
abort ();
for (i = 0; i < XVECLEN (out_pat, 0); i++)
{
rtx exp = XVECEXP (out_pat, 0, i);
if (GET_CODE (exp) == CLOBBER)
continue;
if (GET_CODE (exp) != SET)
abort ();
if (reg_mentioned_p (SET_DEST (exp), SET_DEST (in_set)))
return false;
}
}
return true;
}
/* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE
condition, and not the THEN or ELSE branch. OUT_INSN may be either a single
or multiple set; IN_INSN should be single_set for truth, but for convenience
of insn categorization may be any JUMP or CALL insn. */
int
if_test_bypass_p (out_insn, in_insn)
rtx out_insn, in_insn;
{
rtx out_set, in_set;
in_set = single_set (in_insn);
if (! in_set)
{
if (GET_CODE (in_insn) == JUMP_INSN || GET_CODE (in_insn) == CALL_INSN)
return false;
abort ();
}
if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
return false;
in_set = SET_SRC (in_set);
out_set = single_set (out_insn);
if (out_set)
{
if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
|| reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
return false;
}
else
{
rtx out_pat;
int i;
out_pat = PATTERN (out_insn);
if (GET_CODE (out_pat) != PARALLEL)
abort ();
for (i = 0; i < XVECLEN (out_pat, 0); i++)
{
rtx exp = XVECEXP (out_pat, 0, i);
if (GET_CODE (exp) == CLOBBER)
continue;
if (GET_CODE (exp) != SET)
abort ();
if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
|| reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
return false;
}
}
return true;
}

View File

@ -244,6 +244,7 @@ static enum reg_class find_valid_class PARAMS ((enum machine_mode, int,
unsigned int));
static int reload_inner_reg_of_subreg PARAMS ((rtx, enum machine_mode, int));
static void push_replacement PARAMS ((rtx *, int, enum machine_mode));
static void dup_replacements PARAMS ((rtx *, rtx *));
static void combine_reloads PARAMS ((void));
static int find_reusable_reload PARAMS ((rtx *, rtx, enum reg_class,
enum reload_type, int, int));
@ -257,6 +258,7 @@ static int alternative_allows_memconst PARAMS ((const char *, int));
static rtx find_reloads_toplev PARAMS ((rtx, int, enum reload_type, int,
int, rtx, int *));
static rtx make_memloc PARAMS ((rtx, int));
static int maybe_memory_address_p PARAMS ((enum machine_mode, rtx, rtx *));
static int find_reloads_address PARAMS ((enum machine_mode, rtx *, rtx, rtx *,
int, enum reload_type, int, rtx));
static rtx subst_reg_equivs PARAMS ((rtx, rtx));
@ -275,7 +277,7 @@ static int find_inc_amount PARAMS ((rtx, rtx));
#ifdef HAVE_SECONDARY_RELOADS
/* Determine if any secondary reloads are needed for loading (if IN_P is
non-zero) or storing (if IN_P is zero) X to or from a reload register of
nonzero) or storing (if IN_P is zero) X to or from a reload register of
register class RELOAD_CLASS in mode RELOAD_MODE. If secondary reloads
are needed, push them.
@ -367,7 +369,7 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
if (icode != CODE_FOR_nothing)
{
/* If IN_P is non-zero, the reload register will be the output in
/* If IN_P is nonzero, the reload register will be the output in
operand 0. If IN_P is zero, the reload register will be the input
in operand 1. Outputs should have an initial "=", which we must
skip. */
@ -644,7 +646,7 @@ get_secondary_mem (x, mode, opnum, type)
: type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS
: RELOAD_OTHER);
find_reloads_address (mode, (rtx*) 0, XEXP (loc, 0), &XEXP (loc, 0),
find_reloads_address (mode, &loc, XEXP (loc, 0), &XEXP (loc, 0),
opnum, type, 0, 0);
}
@ -817,6 +819,13 @@ reload_inner_reg_of_subreg (x, mode, output)
|| REGNO (inner) >= FIRST_PSEUDO_REGISTER)
return 0;
if (!subreg_offset_representable_p
(REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x),
GET_MODE (x)))
return 1;
/* If INNER is not ok for MODE, then INNER will need reloading. */
if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
return 1;
@ -828,7 +837,7 @@ reload_inner_reg_of_subreg (x, mode, output)
&& output
&& GET_MODE_SIZE (GET_MODE (inner)) > UNITS_PER_WORD
&& ((GET_MODE_SIZE (GET_MODE (inner)) / UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
!= (int) HARD_REGNO_NREGS (REGNO (inner), GET_MODE (inner))));
}
/* Record one reload that needs to be performed.
@ -837,7 +846,7 @@ reload_inner_reg_of_subreg (x, mode, output)
(IN is zero for data not read, and OUT is zero for data not written.)
INLOC and OUTLOC point to the places in the instructions where
IN and OUT were found.
If IN and OUT are both non-zero, it means the same register must be used
If IN and OUT are both nonzero, it means the same register must be used
to reload both IN and OUT.
CLASS is a register class required for the reloaded data.
@ -966,9 +975,8 @@ push_reload (in, out, inloc, outloc, class,
if (in != 0 && GET_CODE (in) == SUBREG
&& (subreg_lowpart_p (in) || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)), inmode))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (in)), inmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (in))
|| GET_CODE (SUBREG_REG (in)) == PLUS
@ -1005,8 +1013,8 @@ push_reload (in, out, inloc, outloc, class,
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)))))
!= (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
GET_MODE (SUBREG_REG (in)))))
|| ! HARD_REGNO_MODE_OK (subreg_regno (in), inmode)))
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (class, inmode, in) != NO_REGS
@ -1015,14 +1023,11 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (in))
== NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (in)) == REG
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (SUBREG_REG (in))))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (in)),
inmode))
&& REG_CANNOT_CHANGE_MODE_P
(REGNO (SUBREG_REG (in)), GET_MODE (SUBREG_REG (in)), inmode))
#endif
))
{
@ -1080,10 +1085,8 @@ push_reload (in, out, inloc, outloc, class,
and in that case the constraint should label it input-output.) */
if (out != 0 && GET_CODE (out) == SUBREG
&& (subreg_lowpart_p (out) || strict_low)
#ifdef CLASS_CANNOT_CHANGE_MODE
&& (class != CLASS_CANNOT_CHANGE_MODE
|| ! CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
outmode))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& !CANNOT_CHANGE_MODE_CLASS (GET_MODE (SUBREG_REG (out)), outmode, class)
#endif
&& (CONSTANT_P (SUBREG_REG (out))
|| strict_low
@ -1107,8 +1110,8 @@ push_reload (in, out, inloc, outloc, class,
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)))))
!= (int) HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)))))
|| ! HARD_REGNO_MODE_OK (subreg_regno (out), outmode)))
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (class, outmode, out) != NO_REGS
@ -1117,14 +1120,12 @@ push_reload (in, out, inloc, outloc, class,
SUBREG_REG (out))
== NO_REGS))
#endif
#ifdef CLASS_CANNOT_CHANGE_MODE
#ifdef CANNOT_CHANGE_MODE_CLASS
|| (GET_CODE (SUBREG_REG (out)) == REG
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
&& (TEST_HARD_REG_BIT
(reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
REGNO (SUBREG_REG (out))))
&& CLASS_CANNOT_CHANGE_MODE_P (GET_MODE (SUBREG_REG (out)),
outmode))
&& REG_CANNOT_CHANGE_MODE_P (REGNO (SUBREG_REG (out)),
GET_MODE (SUBREG_REG (out)),
outmode))
#endif
))
{
@ -1285,17 +1286,12 @@ push_reload (in, out, inloc, outloc, class,
So add an additional reload. */
#ifdef SECONDARY_MEMORY_NEEDED
{
int regnum;
/* If a memory location is needed for the copy, make one. */
if (in != 0
&& ((regnum = true_regnum (in)) >= 0)
&& regnum < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (regnum),
class, inmode))
get_secondary_mem (in, inmode, opnum, type);
}
/* If a memory location is needed for the copy, make one. */
if (in != 0 && (GET_CODE (in) == REG || GET_CODE (in) == SUBREG)
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
class, inmode))
get_secondary_mem (in, inmode, opnum, type);
#endif
i = n_reloads;
@ -1321,16 +1317,12 @@ push_reload (in, out, inloc, outloc, class,
n_reloads++;
#ifdef SECONDARY_MEMORY_NEEDED
{
int regnum;
if (out != 0
&& ((regnum = true_regnum (out)) >= 0)
&& regnum < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (class, REGNO_REG_CLASS (regnum),
outmode))
get_secondary_mem (out, outmode, opnum, type);
}
if (out != 0 && (GET_CODE (out) == REG || GET_CODE (out) == SUBREG)
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
&& SECONDARY_MEMORY_NEEDED (class,
REGNO_REG_CLASS (reg_or_subregno (out)),
outmode))
get_secondary_mem (out, outmode, opnum, type);
#endif
}
else
@ -1575,6 +1567,25 @@ push_replacement (loc, reloadnum, mode)
r->mode = mode;
}
}
/* Duplicate any replacement we have recorded to apply at
location ORIG_LOC to also be performed at DUP_LOC.
This is used in insn patterns that use match_dup. */
static void
dup_replacements (dup_loc, orig_loc)
rtx *dup_loc;
rtx *orig_loc;
{
int i, n = n_replacements;
for (i = 0; i < n; i++)
{
struct replacement *r = &replacements[i];
if (r->where == orig_loc)
push_replacement (dup_loc, r->what, r->mode);
}
}
/* Transfer all replacements that used to be in reload FROM to be in
reload TO. */
@ -1593,7 +1604,7 @@ transfer_replacements (to, from)
/* IN_RTX is the value loaded by a reload that we now decided to inherit,
or a subpart of it. If we have any replacements registered for IN_RTX,
cancel the reloads that were supposed to load them.
Return non-zero if we canceled any reloads. */
Return nonzero if we canceled any reloads. */
int
remove_address_replacements (in_rtx)
rtx in_rtx;
@ -1833,7 +1844,7 @@ combine_reloads ()
If FOR_REAL is -1, this should not be done, because this call
is just to see if a register can be found, not to find and install it.
EARLYCLOBBER is non-zero if OUT is an earlyclobber operand. This
EARLYCLOBBER is nonzero if OUT is an earlyclobber operand. This
puts an additional constraint on being able to use IN for OUT since
IN must not appear elsewhere in the insn (it is assumed that IN itself
is safe from the earlyclobber). */
@ -2136,13 +2147,13 @@ operands_match_p (x, y)
/* If two operands must match, because they are really a single
operand of an assembler insn, then two postincrements are invalid
because the assembler insn would increment only once.
On the other hand, an postincrement matches ordinary indexing
On the other hand, a postincrement matches ordinary indexing
if the postincrement is the output operand. */
if (code == POST_DEC || code == POST_INC || code == POST_MODIFY)
return operands_match_p (XEXP (x, 0), y);
/* Two preincrements are invalid
because the assembler insn would increment only once.
On the other hand, an preincrement matches ordinary indexing
On the other hand, a preincrement matches ordinary indexing
if the preincrement is the input operand.
In this case, return 2, since some callers need to do special
things when this happens. */
@ -2465,6 +2476,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
char pref_or_nothing[MAX_RECOG_OPERANDS];
/* Nonzero for a MEM operand whose entire address needs a reload. */
int address_reloaded[MAX_RECOG_OPERANDS];
/* Nonzero for an address operand that needs to be completely reloaded. */
int address_operand_reloaded[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use for operand. */
enum reload_type operand_type[MAX_RECOG_OPERANDS];
/* Value of enum reload_type to use within address of operand. */
@ -2643,6 +2656,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
RTX_CODE code = GET_CODE (recog_data.operand[i]);
address_reloaded[i] = 0;
address_operand_reloaded[i] = 0;
operand_type[i] = (modified[i] == RELOAD_READ ? RELOAD_FOR_INPUT
: modified[i] == RELOAD_WRITE ? RELOAD_FOR_OUTPUT
: RELOAD_OTHER);
@ -2654,12 +2668,14 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (*constraints[i] == 0)
/* Ignore things like match_operator operands. */
;
else if (constraints[i][0] == 'p')
else if (constraints[i][0] == 'p'
|| EXTRA_ADDRESS_CONSTRAINT (constraints[i][0]))
{
find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
recog_data.operand[i],
recog_data.operand_loc[i],
i, operand_type[i], ind_levels, insn);
address_operand_reloaded[i]
= find_reloads_address (recog_data.operand_mode[i], (rtx*) 0,
recog_data.operand[i],
recog_data.operand_loc[i],
i, operand_type[i], ind_levels, insn);
/* If we now have a simple operand where we used to have a
PLUS or MULT, re-recognize and try again. */
@ -2676,6 +2692,10 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
recog_data.operand[i] = *recog_data.operand_loc[i];
substed_operand[i] = recog_data.operand[i];
/* Address operands are reloaded in their existing mode,
no matter what is specified in the machine description. */
operand_mode[i] = GET_MODE (recog_data.operand[i]);
}
else if (code == MEM)
{
@ -2856,6 +2876,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
if (!subreg_offset_representable_p
(REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
GET_MODE (operand)))
force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
@ -2911,26 +2937,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
)
#endif
)
/* This following hunk of code should no longer be
needed at all with SUBREG_BYTE. If you need this
code back, please explain to me why so I can
fix the real problem. -DaveM */
#if 0
/* Subreg of a hard reg which can't handle the subreg's mode
or which would handle that mode in the wrong number of
registers for subregging to work. */
|| (GET_CODE (operand) == REG
&& REGNO (operand) < FIRST_PSEUDO_REGISTER
&& ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (operand))
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (operand))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (operand),
GET_MODE (operand))))
|| ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
operand_mode[i])))
#endif
)
force_reload = 1;
}
@ -3154,20 +3160,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
break;
case 'E':
#ifndef REAL_ARITHMETIC
/* Match any floating double constant, but only if
we can examine the bits of it reliably. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& GET_MODE (operand) != VOIDmode && ! flag_pretend_float)
break;
#endif
if (GET_CODE (operand) == CONST_DOUBLE)
win = 1;
break;
case 'F':
if (GET_CODE (operand) == CONST_DOUBLE)
if (GET_CODE (operand) == CONST_DOUBLE
|| (GET_CODE (operand) == CONST_VECTOR
&& (GET_MODE_CLASS (GET_MODE (operand))
== MODE_VECTOR_FLOAT)))
win = 1;
break;
@ -3244,6 +3241,49 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
{
#ifdef EXTRA_CONSTRAINT
if (EXTRA_MEMORY_CONSTRAINT (c))
{
if (force_reload)
break;
if (EXTRA_CONSTRAINT (operand, c))
win = 1;
/* If the address was already reloaded,
we win as well. */
if (GET_CODE (operand) == MEM && address_reloaded[i])
win = 1;
/* Likewise if the address will be reloaded because
reg_equiv_address is nonzero. For reg_equiv_mem
we have to check. */
if (GET_CODE (operand) == REG
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER
&& reg_renumber[REGNO (operand)] < 0
&& ((reg_equiv_mem[REGNO (operand)] != 0
&& EXTRA_CONSTRAINT (reg_equiv_mem[REGNO (operand)], c))
|| (reg_equiv_address[REGNO (operand)] != 0)))
win = 1;
/* If we didn't already win, we can reload
constants via force_const_mem, and other
MEMs by reloading the address like for 'o'. */
if ((CONSTANT_P (operand) && GET_CODE (operand) != HIGH)
|| GET_CODE (operand) == MEM)
badop = 0;
constmemok = 1;
offmemok = 1;
break;
}
if (EXTRA_ADDRESS_CONSTRAINT (c))
{
if (EXTRA_CONSTRAINT (operand, c))
win = 1;
/* If we didn't already win, we can reload
the address into a base register. */
this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
badop = 0;
break;
}
if (EXTRA_CONSTRAINT (operand, c))
win = 1;
#endif
@ -3606,7 +3646,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
for (i = 0; i < noperands; i++)
goal_alternative_matched[i] = -1;
for (i = 0; i < noperands; i++)
if (! goal_alternative_win[i]
&& goal_alternative_matches[i] >= 0)
@ -3810,6 +3850,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
}
else if (goal_alternative_matched[i] < 0
&& goal_alternative_matches[i] < 0
&& !address_operand_reloaded[i]
&& optimize)
{
/* For each non-matching operand that's a MEM or a pseudo-register
@ -3957,9 +3998,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
{
int opno = recog_data.dup_num[i];
*recog_data.dup_loc[i] = *recog_data.operand_loc[opno];
if (operand_reloadnum[opno] >= 0)
push_replacement (recog_data.dup_loc[i], operand_reloadnum[opno],
insn_data[insn_code_number].operand[opno].mode);
dup_replacements (recog_data.dup_loc[i], recog_data.operand_loc[opno]);
}
#if 0
@ -4313,7 +4352,7 @@ alternative_allows_memconst (constraint, altnum)
/* Scan the requested alternative for 'm' or 'o'.
If one of them is present, this alternative accepts memory constants. */
while ((c = *constraint++) && c != ',' && c != '#')
if (c == 'm' || c == 'o')
if (c == 'm' || c == 'o' || EXTRA_MEMORY_CONSTRAINT (c))
return 1;
return 0;
}
@ -4438,34 +4477,6 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest, insn,
return tem;
}
/* If the SUBREG is wider than a word, the above test will fail.
For example, we might have a SImode SUBREG of a DImode SUBREG_REG
for a 16 bit target, or a DImode SUBREG of a TImode SUBREG_REG for
a 32 bit target. We still can - and have to - handle this
for non-paradoxical subregs of CONST_INTs. */
if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0
&& GET_CODE (reg_equiv_constant[regno]) == CONST_INT
&& (GET_MODE_SIZE (GET_MODE (x))
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
{
int shift = SUBREG_BYTE (x) * BITS_PER_UNIT;
if (WORDS_BIG_ENDIAN)
shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x)))
- GET_MODE_BITSIZE (GET_MODE (x))
- shift);
/* Here we use the knowledge that CONST_INTs have a
HOST_WIDE_INT field. */
if (shift >= HOST_BITS_PER_WIDE_INT)
shift = HOST_BITS_PER_WIDE_INT - 1;
return GEN_INT (INTVAL (reg_equiv_constant[regno]) >> shift);
}
if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0
&& reg_equiv_constant[regno] != 0
&& GET_MODE (reg_equiv_constant[regno]) == VOIDmode)
abort ();
/* If the subreg contains a reg that will be converted to a mem,
convert the subreg to a narrower memref now.
Otherwise, we would get (subreg (mem ...) ...),
@ -4545,6 +4556,27 @@ make_memloc (ad, regno)
return tem;
}
/* Returns true if AD could be turned into a valid memory reference
to mode MODE by reloading the part pointed to by PART into a
register. */
static int
maybe_memory_address_p (mode, ad, part)
enum machine_mode mode;
rtx ad;
rtx *part;
{
int retv;
rtx tem = *part;
rtx reg = gen_rtx_REG (GET_MODE (tem), max_reg_num ());
*part = reg;
retv = memory_address_p (mode, ad);
*part = tem;
return retv;
}
/* Record all reloads needed for handling memory address AD
which appears in *LOC in a memory reference to mode MODE
which itself is found in location *MEMREFLOC.
@ -4611,9 +4643,9 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
tem = make_memloc (ad, regno);
if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
{
find_reloads_address (GET_MODE (tem), (rtx*) 0, XEXP (tem, 0),
&XEXP (tem, 0), opnum, ADDR_TYPE (type),
ind_levels, insn);
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
ADDR_TYPE (type), ind_levels, insn);
}
/* We can avoid a reload if the register's equivalent memory
expression is valid as an indirect memory address.
@ -4825,26 +4857,24 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
that the index needs a reload and find_reloads_address_1 will take care
of it.
If we decide to do something here, it must be that
`double_reg_address_ok' is true and that this address rtl was made by
eliminate_regs. We generate a reload of the fp/sp/ap + constant and
Handle all base registers here, not just fp/ap/sp, because on some
targets (namely Sparc) we can also get invalid addresses from preventive
subreg big-endian corrections made by find_reloads_toplev.
If we decide to do something, it must be that `double_reg_address_ok'
is true. We generate a reload of the base register + constant and
rework the sum so that the reload register will be added to the index.
This is safe because we know the address isn't shared.
We check for fp/ap/sp as both the first and second operand of the
innermost PLUS. */
We check for the base register as both the first and second operand of
the innermost PLUS. */
else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
&& GET_CODE (XEXP (ad, 0)) == PLUS
&& (XEXP (XEXP (ad, 0), 0) == frame_pointer_rtx
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
|| XEXP (XEXP (ad, 0), 0) == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| XEXP (XEXP (ad, 0), 0) == arg_pointer_rtx
#endif
|| XEXP (XEXP (ad, 0), 0) == stack_pointer_rtx)
&& ! memory_address_p (mode, ad))
&& GET_CODE (XEXP (XEXP (ad, 0), 0)) == REG
&& REGNO (XEXP (XEXP (ad, 0), 0)) < FIRST_PSEUDO_REGISTER
&& REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 0), mode)
&& ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 1)))
{
*loc = ad = gen_rtx_PLUS (GET_MODE (ad),
plus_constant (XEXP (XEXP (ad, 0), 0),
@ -4861,15 +4891,10 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
else if (GET_CODE (ad) == PLUS && GET_CODE (XEXP (ad, 1)) == CONST_INT
&& GET_CODE (XEXP (ad, 0)) == PLUS
&& (XEXP (XEXP (ad, 0), 1) == frame_pointer_rtx
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
|| XEXP (XEXP (ad, 0), 1) == hard_frame_pointer_rtx
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
|| XEXP (XEXP (ad, 0), 1) == arg_pointer_rtx
#endif
|| XEXP (XEXP (ad, 0), 1) == stack_pointer_rtx)
&& ! memory_address_p (mode, ad))
&& GET_CODE (XEXP (XEXP (ad, 0), 1)) == REG
&& REGNO (XEXP (XEXP (ad, 0), 1)) < FIRST_PSEUDO_REGISTER
&& REG_MODE_OK_FOR_BASE_P (XEXP (XEXP (ad, 0), 1), mode)
&& ! maybe_memory_address_p (mode, ad, &XEXP (XEXP (ad, 0), 0)))
{
*loc = ad = gen_rtx_PLUS (GET_MODE (ad),
XEXP (XEXP (ad, 0), 0),
@ -5214,6 +5239,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
SUBREG_BYTE (orig_op1),
GET_MODE (orig_op1))));
}
/* Plus in the index register may be created only as a result of
register remateralization for expresion like &localvar*4. Reload it.
It may be possible to combine the displacement on the outer level,
but it is probably not worthwhile to do so. */
if (context)
{
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
(context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)
@ -5341,7 +5379,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
We can't use ADDR_TYPE (type) here, because we need to
write back the value after reading it, hence we actually
need two registers. */
find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0),
find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
&XEXP (tem, 0), opnum,
RELOAD_OTHER,
ind_levels, insn);
@ -5644,7 +5682,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
{
enum reg_class class = (context ? INDEX_REG_CLASS
: MODE_BASE_REG_CLASS (mode));
if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
if ((unsigned) CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
> reg_class_size[class])
{
x = find_reloads_subreg_address (x, 0, opnum, type,
@ -5988,7 +6026,7 @@ copy_replacements_1 (px, py, orig_replacements)
}
}
/* Change any replacements being done to *X to be done to *Y */
/* Change any replacements being done to *X to be done to *Y. */
void
move_replacements (x, y)
@ -6859,7 +6897,7 @@ regno_clobbered_p (regno, insn, mode, sets)
&& GET_CODE (XEXP (elt, 0)) == REG)
{
unsigned int test = REGNO (XEXP (elt, 0));
if (test >= regno && test < endregno)
return 1;
}