mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-27 08:00:11 +00:00
Virgin import of the GCC 2.95.1 compilers
This commit is contained in:
parent
aef9219924
commit
f2c57ef828
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/vendor/gcc/dist/; revision=52284
@ -1,9 +1,9 @@
|
||||
If you think you may have found a bug in GNU CC, please
|
||||
If you think you may have found a bug in GCC, please
|
||||
read the Bugs section of the GCC manual for advice on
|
||||
|
||||
(1) how to tell when to report a bug,
|
||||
(2) where to send your bug report, and
|
||||
(2) how to write a useful bug report and what information
|
||||
(3) how to write a useful bug report and what information
|
||||
it needs to have.
|
||||
|
||||
There are three ways to read the Bugs section.
|
||||
@ -20,4 +20,8 @@ to get to the section on bugs. Or use standalone Info in
|
||||
a like manner. (Standalone Info is part of the Texinfo distribution.)
|
||||
|
||||
(3) By hand. Search for the chapter "Reporting Bugs" in gcc.texi, or
|
||||
cat /usr/local/info/gcc* | more "+/^File: emacs, Node: Bugs,"
|
||||
cat /usr/local/info/gcc* | more "+/^File: gcc.info, Node: Bugs,"
|
||||
|
||||
You may also want to take a look at the GCC FAQ, in which there are
|
||||
additional instructions for submitting bug reports:
|
||||
http://www.gnu.org/software/gcc/faq.html#bugreport
|
||||
|
29678
contrib/gcc/ChangeLog
29678
contrib/gcc/ChangeLog
File diff suppressed because it is too large
Load Diff
2154
contrib/gcc/FSFChangeLog
Normal file
2154
contrib/gcc/FSFChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,18 @@ time as we can formally start documenting the interface this file will
|
||||
serve as a repository for information on these interface and any incompatable
|
||||
changes we've made.
|
||||
|
||||
Aug 31, 1998:
|
||||
The interface to HANDLE_PRAGMA has changed. It now takes three arguments.
|
||||
The first two are pointers to functions that should be used to read characters
|
||||
from the input stream, and to push them back into the input stream respectively.
|
||||
The third argument is a pointer to a null terminate string which is the first
|
||||
word after #pragma. The expression supplied by HANDLE_PRAGMA should return
|
||||
non-zero if it parsed and implemented the pragma. Otherwise it should return
|
||||
zero, and leave the input stream as it was before the expression was evaluated.
|
||||
|
||||
A new back-end definable macro has been added: INSERT_ATTRIBUTES. This macro
|
||||
allows backend to add attributes to decls as they are created.
|
||||
|
||||
Jun 10, 1998:
|
||||
The interface to lang_decode_option has changed. It now uses and argc/argv
|
||||
interface to allow for options that use more than one input string. The new
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,11 @@
|
||||
Noteworthy changes in GCC after EGCS 1.1.
|
||||
-----------------------------------------
|
||||
|
||||
Target specific NEWS
|
||||
|
||||
RS6000/PowerPC: -mcpu=401 was added as an alias for -mcpu=403. -mcpu=e603e
|
||||
was added to do -mcpu=603e and -msoft-float.
|
||||
|
||||
Noteworthy changes in GCC for EGCS 1.1.
|
||||
---------------------------------------
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
This directory contains the egcs version 1.1.2 release of the GNU C
|
||||
compiler. It includes all of the support for compiling C++ and
|
||||
Objective C, including a run-time library for Objective C.
|
||||
This directory contains the GNU Compiler Collection (GCC) version 2.95.
|
||||
It includes all of the support for compiling C, C++, Objective C, Fortran,
|
||||
Java, and Chill.
|
||||
|
||||
The GNU C compiler is free software. See the file COPYING for copying
|
||||
The GNU Compiler Collection is free software. See the file COPYING for copying
|
||||
permission.
|
||||
|
||||
See the file gcc.texi (together with other files that it includes) for
|
||||
|
@ -1,9 +1,21 @@
|
||||
/* Define if you can safely include both <string.h> and <strings.h>. */
|
||||
#undef STRING_WITH_STRINGS
|
||||
|
||||
/* Define if printf supports "%p". */
|
||||
#undef HAVE_PRINTF_PTR
|
||||
|
||||
/* Define if you want expensive run-time checks. */
|
||||
#undef ENABLE_CHECKING
|
||||
|
||||
/* Define to 1 if NLS is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
|
||||
#undef HAVE_CATGETS
|
||||
|
||||
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define if your cpp understands the stringify operator. */
|
||||
#undef HAVE_CPP_STRINGIFY
|
||||
|
||||
@ -17,9 +29,22 @@
|
||||
/* Define if your assembler supports .balign and .p2align. */
|
||||
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
|
||||
|
||||
/* Define if your assembler supports .subsection and .subsection -1 starts
|
||||
emitting at the beginning of your section */
|
||||
#undef HAVE_GAS_SUBSECTION_ORDERING
|
||||
|
||||
/* Define if your assembler uses the old HImode fild and fist notation. */
|
||||
#undef HAVE_GAS_FILDS_FISTS
|
||||
|
||||
/* Define if you have a working <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||
#undef HAVE_LC_MESSAGES
|
||||
|
||||
/* Define as 1 if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Whether malloc must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_MALLOC
|
||||
|
||||
@ -53,6 +78,9 @@
|
||||
/* Whether atol must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_ATOL
|
||||
|
||||
/* Whether atof must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_ATOF
|
||||
|
||||
/* Whether sbrk must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_SBRK
|
||||
|
||||
@ -62,6 +90,12 @@
|
||||
/* Whether strerror must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRERROR
|
||||
|
||||
/* Whether strsignal must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRSIGNAL
|
||||
|
||||
/* Whether strstr must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRSTR
|
||||
|
||||
/* Whether getcwd must be declared even if <unistd.h> is included. */
|
||||
#undef NEED_DECLARATION_GETCWD
|
||||
|
||||
@ -74,6 +108,24 @@
|
||||
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
|
||||
#undef NEED_DECLARATION_SETRLIMIT
|
||||
|
||||
/* Define if you want expensive run-time checks. */
|
||||
#undef ENABLE_CHECKING
|
||||
/* Whether putc_unlocked must be declared even if <stdio.h> is included. */
|
||||
#undef NEED_DECLARATION_PUTC_UNLOCKED
|
||||
|
||||
/* Whether fputs_unlocked must be declared even if <stdio.h> is included. */
|
||||
#undef NEED_DECLARATION_FPUTS_UNLOCKED
|
||||
|
||||
/* Define to enable the use of a default assembler. */
|
||||
#undef DEFAULT_ASSEMBLER
|
||||
|
||||
/* Define to enable the use of a default linker. */
|
||||
#undef DEFAULT_LINKER
|
||||
|
||||
/* Define if host mkdir takes a single argument. */
|
||||
#undef MKDIR_TAKES_ONE_ARG
|
||||
|
||||
/* Define to the name of the distribution. */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the version of the distribution. */
|
||||
#undef VERSION
|
||||
@TOP@
|
||||
|
448
contrib/gcc/aclocal.m4
vendored
448
contrib/gcc/aclocal.m4
vendored
@ -1,3 +1,14 @@
|
||||
dnl See whether we can include both string.h and strings.h.
|
||||
AC_DEFUN(GCC_HEADER_STRING,
|
||||
[AC_CACHE_CHECK([whether string.h and strings.h may both be included],
|
||||
gcc_cv_header_string,
|
||||
[AC_TRY_COMPILE([#include <string.h>
|
||||
#include <strings.h>], , gcc_cv_header_string=yes, gcc_cv_header_string=no)])
|
||||
if test $gcc_cv_header_string = yes; then
|
||||
AC_DEFINE(STRING_WITH_STRINGS)
|
||||
fi
|
||||
])
|
||||
|
||||
dnl See whether we need a declaration for a function.
|
||||
dnl GCC_NEED_DECLARATION(FUNCTION [, EXTRA-HEADER-FILES])
|
||||
AC_DEFUN(GCC_NEED_DECLARATION,
|
||||
@ -5,12 +16,17 @@ AC_DEFUN(GCC_NEED_DECLARATION,
|
||||
AC_CACHE_VAL(gcc_cv_decl_needed_$1,
|
||||
[AC_TRY_COMPILE([
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#ifdef STRING_WITH_STRINGS
|
||||
# include <string.h>
|
||||
# include <strings.h>
|
||||
#else
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
# ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
# else
|
||||
# ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
@ -156,6 +172,27 @@ if test $gcc_cv_c_volatile = yes ; then
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
|
||||
dnl of the usual 2.
|
||||
AC_DEFUN(GCC_FUNC_MKDIR_TAKES_ONE_ARG,
|
||||
[AC_CACHE_CHECK([if mkdir takes one argument], gcc_cv_mkdir_takes_one_arg,
|
||||
[AC_TRY_COMPILE([
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRECT_H
|
||||
# include <direct.h>
|
||||
#endif], [mkdir ("foo", 0);],
|
||||
gcc_cv_mkdir_takes_one_arg=no, gcc_cv_mkdir_takes_one_arg=yes)])
|
||||
if test $gcc_cv_mkdir_takes_one_arg = yes ; then
|
||||
AC_DEFINE(MKDIR_TAKES_ONE_ARG)
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN(EGCS_PROG_INSTALL,
|
||||
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
@ -219,3 +256,404 @@ AC_SUBST(INSTALL_PROGRAM)dnl
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
AC_SUBST(INSTALL_DATA)dnl
|
||||
])
|
||||
|
||||
#serial 1
|
||||
dnl This test replaces the one in autoconf.
|
||||
dnl Currently this macro should have the same name as the autoconf macro
|
||||
dnl because gettext's gettext.m4 (distributed in the automake package)
|
||||
dnl still uses it. Otherwise, the use in gettext.m4 makes autoheader
|
||||
dnl give these diagnostics:
|
||||
dnl configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX
|
||||
dnl configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX
|
||||
|
||||
undefine([AC_ISC_POSIX])
|
||||
AC_DEFUN(AC_ISC_POSIX,
|
||||
[
|
||||
dnl This test replaces the obsolescent AC_ISC_POSIX kludge.
|
||||
AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"])
|
||||
]
|
||||
)
|
||||
|
||||
# Macro to add for using GNU gettext.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
#
|
||||
# This file can be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU Public License
|
||||
# but which still want to provide support for the GNU gettext functionality.
|
||||
# Please note that the actual code is *not* freely available.
|
||||
|
||||
# serial 5
|
||||
|
||||
AC_DEFUN(AM_WITH_NLS,
|
||||
[AC_MSG_CHECKING([whether NLS is requested])
|
||||
dnl Default is enabled NLS
|
||||
AC_ARG_ENABLE(nls,
|
||||
[ --disable-nls do not use Native Language Support],
|
||||
USE_NLS=$enableval, USE_NLS=yes)
|
||||
AC_MSG_RESULT($USE_NLS)
|
||||
AC_SUBST(USE_NLS)
|
||||
|
||||
USE_INCLUDED_LIBINTL=no
|
||||
|
||||
dnl If we use NLS figure out what method
|
||||
if test "$USE_NLS" = "yes"; then
|
||||
AC_DEFINE(ENABLE_NLS)
|
||||
AC_MSG_CHECKING([whether included gettext is requested])
|
||||
AC_ARG_WITH(included-gettext,
|
||||
[ --with-included-gettext use the GNU gettext library included here],
|
||||
nls_cv_force_use_gnu_gettext=$withval,
|
||||
nls_cv_force_use_gnu_gettext=no)
|
||||
AC_MSG_RESULT($nls_cv_force_use_gnu_gettext)
|
||||
|
||||
nls_cv_use_gnu_gettext="$nls_cv_force_use_gnu_gettext"
|
||||
if test "$nls_cv_force_use_gnu_gettext" != "yes"; then
|
||||
dnl User does not insist on using GNU NLS library. Figure out what
|
||||
dnl to use. If gettext or catgets are available (in this order) we
|
||||
dnl use this. Else we have to fall back to GNU NLS library.
|
||||
dnl catgets is only used if permitted by option --with-catgets.
|
||||
nls_cv_header_intl=
|
||||
nls_cv_header_libgt=
|
||||
CATOBJEXT=NONE
|
||||
|
||||
AC_CHECK_HEADER(libintl.h,
|
||||
[AC_CACHE_CHECK([for gettext in libc], gt_cv_func_gettext_libc,
|
||||
[AC_TRY_LINK([#include <libintl.h>], [return (int) gettext ("")],
|
||||
gt_cv_func_gettext_libc=yes, gt_cv_func_gettext_libc=no)])
|
||||
|
||||
if test "$gt_cv_func_gettext_libc" != "yes"; then
|
||||
AC_CHECK_LIB(intl, bindtextdomain,
|
||||
[AC_CACHE_CHECK([for gettext in libintl],
|
||||
gt_cv_func_gettext_libintl,
|
||||
[AC_CHECK_LIB(intl, gettext,
|
||||
gt_cv_func_gettext_libintl=yes,
|
||||
gt_cv_func_gettext_libintl=no)],
|
||||
gt_cv_func_gettext_libintl=no)])
|
||||
fi
|
||||
|
||||
if test "$gt_cv_func_gettext_libc" = "yes" \
|
||||
|| test "$gt_cv_func_gettext_libintl" = "yes"; then
|
||||
AC_DEFINE(HAVE_GETTEXT)
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl
|
||||
if test "$MSGFMT" != "no"; then
|
||||
AC_CHECK_FUNCS(dcgettext)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
AC_TRY_LINK(, [extern int _nl_msg_cat_cntr;
|
||||
return _nl_msg_cat_cntr],
|
||||
[CATOBJEXT=.gmo
|
||||
DATADIRNAME=share],
|
||||
[CATOBJEXT=.mo
|
||||
DATADIRNAME=lib])
|
||||
INSTOBJEXT=.mo
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$CATOBJEXT" = "NONE"; then
|
||||
AC_MSG_CHECKING([whether catgets can be used])
|
||||
AC_ARG_WITH(catgets,
|
||||
[ --with-catgets use catgets functions if available],
|
||||
nls_cv_use_catgets=$withval, nls_cv_use_catgets=no)
|
||||
AC_MSG_RESULT($nls_cv_use_catgets)
|
||||
|
||||
if test "$nls_cv_use_catgets" = "yes"; then
|
||||
dnl No gettext in C library. Try catgets next.
|
||||
AC_CHECK_LIB(i, main)
|
||||
AC_CHECK_FUNC(catgets,
|
||||
[AC_DEFINE(HAVE_CATGETS)
|
||||
INTLOBJS="\$(CATOBJS)"
|
||||
AC_PATH_PROG(GENCAT, gencat, no)dnl
|
||||
if test "$GENCAT" != "no"; then
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, no)
|
||||
if test "$GMSGFMT" = "no"; then
|
||||
AM_PATH_PROG_WITH_TEST(GMSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)
|
||||
fi
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
CATOBJEXT=.cat
|
||||
INSTOBJEXT=.cat
|
||||
DATADIRNAME=lib
|
||||
INTLDEPS='$(top_builddir)/intl/libintl.a'
|
||||
INTLLIBS=$INTLDEPS
|
||||
LIBS=`echo $LIBS | sed -e 's/-lintl//'`
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$CATOBJEXT" = "NONE"; then
|
||||
dnl Neither gettext nor catgets in included in the C library.
|
||||
dnl Fall back on GNU gettext library.
|
||||
nls_cv_use_gnu_gettext=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$nls_cv_use_gnu_gettext" = "yes"; then
|
||||
dnl Mark actions used to generate GNU NLS library.
|
||||
INTLOBJS="\$(GETTOBJS)"
|
||||
AM_PATH_PROG_WITH_TEST(MSGFMT, msgfmt,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], msgfmt)
|
||||
AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT)
|
||||
AM_PATH_PROG_WITH_TEST(XGETTEXT, xgettext,
|
||||
[test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :)
|
||||
AC_SUBST(MSGFMT)
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
CATOBJEXT=.gmo
|
||||
INSTOBJEXT=.mo
|
||||
DATADIRNAME=share
|
||||
INTLDEPS='$(top_builddir)/intl/libintl.a'
|
||||
INTLLIBS=$INTLDEPS
|
||||
LIBS=`echo $LIBS | sed -e 's/-lintl//'`
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi
|
||||
|
||||
dnl Test whether we really found GNU xgettext.
|
||||
if test "$XGETTEXT" != ":"; then
|
||||
dnl If it is no GNU xgettext we define it as : so that the
|
||||
dnl Makefiles still can work.
|
||||
if $XGETTEXT --omit-header /dev/null 2> /dev/null; then
|
||||
: ;
|
||||
else
|
||||
AC_MSG_RESULT(
|
||||
[found xgettext program is not GNU xgettext; ignore it])
|
||||
XGETTEXT=":"
|
||||
fi
|
||||
fi
|
||||
|
||||
# We need to process the po/ directory.
|
||||
POSUB=po
|
||||
else
|
||||
DATADIRNAME=share
|
||||
nls_cv_header_intl=intl/libintl.h
|
||||
nls_cv_header_libgt=intl/libgettext.h
|
||||
fi
|
||||
AC_LINK_FILES($nls_cv_header_libgt, $nls_cv_header_intl)
|
||||
AC_OUTPUT_COMMANDS(
|
||||
[case "$CONFIG_FILES" in *po/Makefile.in*)
|
||||
sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile
|
||||
esac])
|
||||
|
||||
|
||||
# If this is used in GNU gettext we have to set USE_NLS to `yes'
|
||||
# because some of the sources are only built for this goal.
|
||||
if test "$PACKAGE" = gettext; then
|
||||
USE_NLS=yes
|
||||
USE_INCLUDED_LIBINTL=yes
|
||||
fi
|
||||
|
||||
dnl These rules are solely for the distribution goal. While doing this
|
||||
dnl we only have to keep exactly one list of the available catalogs
|
||||
dnl in configure.in.
|
||||
for lang in $ALL_LINGUAS; do
|
||||
GMOFILES="$GMOFILES $lang.gmo"
|
||||
POFILES="$POFILES $lang.po"
|
||||
done
|
||||
|
||||
dnl Make all variables we use known to autoconf.
|
||||
AC_SUBST(USE_INCLUDED_LIBINTL)
|
||||
AC_SUBST(CATALOGS)
|
||||
AC_SUBST(CATOBJEXT)
|
||||
AC_SUBST(DATADIRNAME)
|
||||
AC_SUBST(GMOFILES)
|
||||
AC_SUBST(INSTOBJEXT)
|
||||
AC_SUBST(INTLDEPS)
|
||||
AC_SUBST(INTLLIBS)
|
||||
AC_SUBST(INTLOBJS)
|
||||
AC_SUBST(POFILES)
|
||||
AC_SUBST(POSUB)
|
||||
])
|
||||
|
||||
AC_DEFUN(AM_GNU_GETTEXT,
|
||||
[AC_REQUIRE([AC_PROG_MAKE_SET])dnl
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_PROG_RANLIB])dnl
|
||||
AC_REQUIRE([AC_ISC_POSIX])dnl
|
||||
AC_REQUIRE([AC_HEADER_STDC])dnl
|
||||
AC_REQUIRE([AC_C_CONST])dnl
|
||||
AC_REQUIRE([AC_C_INLINE])dnl
|
||||
AC_REQUIRE([AC_TYPE_OFF_T])dnl
|
||||
AC_REQUIRE([AC_TYPE_SIZE_T])dnl
|
||||
AC_REQUIRE([AC_FUNC_ALLOCA])dnl
|
||||
AC_REQUIRE([AC_FUNC_MMAP])dnl
|
||||
|
||||
AC_CHECK_HEADERS([argz.h limits.h locale.h nl_types.h malloc.h string.h \
|
||||
unistd.h sys/param.h])
|
||||
AC_CHECK_FUNCS([getcwd munmap putenv setenv setlocale strchr strcasecmp \
|
||||
strdup __argz_count __argz_stringify __argz_next])
|
||||
|
||||
if test "${ac_cv_func_stpcpy+set}" != "set"; then
|
||||
AC_CHECK_FUNCS(stpcpy)
|
||||
fi
|
||||
if test "${ac_cv_func_stpcpy}" = "yes"; then
|
||||
AC_DEFINE(HAVE_STPCPY)
|
||||
fi
|
||||
|
||||
AM_LC_MESSAGES
|
||||
AM_WITH_NLS
|
||||
|
||||
if test "x$CATOBJEXT" != "x"; then
|
||||
if test "x$ALL_LINGUAS" = "x"; then
|
||||
LINGUAS=
|
||||
else
|
||||
AC_MSG_CHECKING(for catalogs to be installed)
|
||||
NEW_LINGUAS=
|
||||
for lang in ${LINGUAS=$ALL_LINGUAS}; do
|
||||
case "$ALL_LINGUAS" in
|
||||
*$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;;
|
||||
esac
|
||||
done
|
||||
LINGUAS=$NEW_LINGUAS
|
||||
AC_MSG_RESULT($LINGUAS)
|
||||
fi
|
||||
|
||||
dnl Construct list of names of catalog files to be constructed.
|
||||
if test -n "$LINGUAS"; then
|
||||
for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl The reference to <locale.h> in the installed <libintl.h> file
|
||||
dnl must be resolved because we cannot expect the users of this
|
||||
dnl to define HAVE_LOCALE_H.
|
||||
if test $ac_cv_header_locale_h = yes; then
|
||||
INCLUDE_LOCALE_H="#include <locale.h>"
|
||||
else
|
||||
INCLUDE_LOCALE_H="\
|
||||
/* The system does not provide the header <locale.h>. Take care yourself. */"
|
||||
fi
|
||||
AC_SUBST(INCLUDE_LOCALE_H)
|
||||
|
||||
dnl Determine which catalog format we have (if any is needed)
|
||||
dnl For now we know about two different formats:
|
||||
dnl Linux libc-5 and the normal X/Open format
|
||||
test -d intl || mkdir intl
|
||||
if test "$CATOBJEXT" = ".cat"; then
|
||||
AC_CHECK_HEADER(linux/version.h, msgformat=linux, msgformat=xopen)
|
||||
|
||||
dnl Transform the SED scripts while copying because some dumb SEDs
|
||||
dnl cannot handle comments.
|
||||
sed -e '/^#/d' $srcdir/intl/$msgformat-msg.sed > intl/po2msg.sed
|
||||
fi
|
||||
dnl po2tbl.sed is always needed.
|
||||
sed -e '/^#.*[^\\]$/d' -e '/^#$/d' \
|
||||
$srcdir/intl/po2tbl.sed.in > intl/po2tbl.sed
|
||||
|
||||
dnl In the intl/Makefile.in we have a special dependency which makes
|
||||
dnl only sense for gettext. We comment this out for non-gettext
|
||||
dnl packages.
|
||||
if test "$PACKAGE" = "gettext"; then
|
||||
GT_NO="#NO#"
|
||||
GT_YES=
|
||||
else
|
||||
GT_NO=
|
||||
GT_YES="#YES#"
|
||||
fi
|
||||
AC_SUBST(GT_NO)
|
||||
AC_SUBST(GT_YES)
|
||||
|
||||
dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly
|
||||
dnl find the mkinstalldirs script in another subdir but ($top_srcdir).
|
||||
dnl Try to locate is.
|
||||
MKINSTALLDIRS=
|
||||
if test -n "$ac_aux_dir"; then
|
||||
MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs"
|
||||
fi
|
||||
if test -z "$MKINSTALLDIRS"; then
|
||||
MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs"
|
||||
fi
|
||||
AC_SUBST(MKINSTALLDIRS)
|
||||
|
||||
dnl *** For now the libtool support in intl/Makefile is not for real.
|
||||
l=
|
||||
AC_SUBST(l)
|
||||
|
||||
dnl Generate list of files to be processed by xgettext which will
|
||||
dnl be included in po/Makefile.
|
||||
test -d po || mkdir po
|
||||
if test "x$srcdir" != "x."; then
|
||||
if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then
|
||||
posrcprefix="$srcdir/"
|
||||
else
|
||||
posrcprefix="../$srcdir/"
|
||||
fi
|
||||
else
|
||||
posrcprefix="../"
|
||||
fi
|
||||
rm -f po/POTFILES
|
||||
sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \
|
||||
< $srcdir/po/POTFILES.in > po/POTFILES
|
||||
])
|
||||
|
||||
# Check whether LC_MESSAGES is available in <locale.h>.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
#
|
||||
# This file can be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU Public License
|
||||
# but which still want to provide support for the GNU gettext functionality.
|
||||
# Please note that the actual code is *not* freely available.
|
||||
|
||||
# serial 1
|
||||
|
||||
AC_DEFUN(AM_LC_MESSAGES,
|
||||
[if test $ac_cv_header_locale_h = yes; then
|
||||
AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES,
|
||||
[AC_TRY_LINK([#include <locale.h>], [return LC_MESSAGES],
|
||||
am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)])
|
||||
if test $am_cv_val_LC_MESSAGES = yes; then
|
||||
AC_DEFINE(HAVE_LC_MESSAGES)
|
||||
fi
|
||||
fi])
|
||||
|
||||
# Search path for a program which passes the given test.
|
||||
# Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||||
#
|
||||
# This file can be copied and used freely without restrictions. It can
|
||||
# be used in projects which are not available under the GNU Public License
|
||||
# but which still want to provide support for the GNU gettext functionality.
|
||||
# Please note that the actual code is *not* freely available.
|
||||
|
||||
# serial 1
|
||||
|
||||
dnl AM_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR,
|
||||
dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]])
|
||||
AC_DEFUN(AM_PATH_PROG_WITH_TEST,
|
||||
[# Extract the first word of "$2", so it can be a program name with args.
|
||||
set dummy $2; ac_word=[$]2
|
||||
AC_MSG_CHECKING([for $ac_word])
|
||||
AC_CACHE_VAL(ac_cv_path_$1,
|
||||
[case "[$]$1" in
|
||||
/*)
|
||||
ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
|
||||
;;
|
||||
*)
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in ifelse([$5], , $PATH, [$5]); do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f $ac_dir/$ac_word; then
|
||||
if [$3]; then
|
||||
ac_cv_path_$1="$ac_dir/$ac_word"
|
||||
break
|
||||
fi
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
dnl If no 4th arg is given, leave the cache variable unset,
|
||||
dnl so AC_PATH_PROGS will keep looking.
|
||||
ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4"
|
||||
])dnl
|
||||
;;
|
||||
esac])dnl
|
||||
$1="$ac_cv_path_$1"
|
||||
if test -n "[$]$1"; then
|
||||
AC_MSG_RESULT([$]$1)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST($1)dnl
|
||||
])
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Alias analysis for GNU C
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
Contributed by John Carr (jfc@mit.edu).
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -26,7 +26,51 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "flags.h"
|
||||
#include "output.h"
|
||||
#include "toplev.h"
|
||||
#include "splay-tree.h"
|
||||
|
||||
/* The alias sets assigned to MEMs assist the back-end in determining
|
||||
which MEMs can alias which other MEMs. In general, two MEMs in
|
||||
different alias sets to not alias each other. There is one
|
||||
exception, however. Consider something like:
|
||||
|
||||
struct S {int i; double d; };
|
||||
|
||||
a store to an `S' can alias something of either type `int' or type
|
||||
`double'. (However, a store to an `int' cannot alias a `double'
|
||||
and vice versa.) We indicate this via a tree structure that looks
|
||||
like:
|
||||
struct S
|
||||
/ \
|
||||
/ \
|
||||
|/_ _\|
|
||||
int double
|
||||
|
||||
(The arrows are directed and point downwards.) If, when comparing
|
||||
two alias sets, we can hold one set fixed, and trace the other set
|
||||
downwards, and at some point find the first set, the two MEMs can
|
||||
alias one another. In this situation we say the alias set for
|
||||
`struct S' is the `superset' and that those for `int' and `double'
|
||||
are `subsets'.
|
||||
|
||||
Alias set zero is implicitly a superset of all other alias sets.
|
||||
However, this is no actual entry for alias set zero. It is an
|
||||
error to attempt to explicitly construct a subset of zero. */
|
||||
|
||||
typedef struct alias_set_entry {
|
||||
/* The alias set number, as stored in MEM_ALIAS_SET. */
|
||||
int alias_set;
|
||||
|
||||
/* The children of the alias set. These are not just the immediate
|
||||
children, but, in fact, all children. So, if we have:
|
||||
|
||||
struct T { struct S s; float f; }
|
||||
|
||||
continuing our example above, the children here will be all of
|
||||
`int', `double', `float', and `struct S'. */
|
||||
splay_tree children;
|
||||
}* alias_set_entry;
|
||||
|
||||
static rtx canon_rtx PROTO((rtx));
|
||||
static int rtx_equal_for_memref_p PROTO((rtx, rtx));
|
||||
@ -35,34 +79,27 @@ static int memrefs_conflict_p PROTO((int, rtx, int, rtx,
|
||||
HOST_WIDE_INT));
|
||||
static void record_set PROTO((rtx, rtx));
|
||||
static rtx find_base_term PROTO((rtx));
|
||||
static int base_alias_check PROTO((rtx, rtx));
|
||||
static int base_alias_check PROTO((rtx, rtx, enum machine_mode,
|
||||
enum machine_mode));
|
||||
static rtx find_base_value PROTO((rtx));
|
||||
static int mems_in_disjoint_alias_sets_p PROTO((rtx, rtx));
|
||||
static int insert_subset_children PROTO((splay_tree_node,
|
||||
void*));
|
||||
static alias_set_entry get_alias_set_entry PROTO((int));
|
||||
static rtx fixed_scalar_and_varying_struct_p PROTO((rtx, rtx, int (*)(rtx)));
|
||||
static int aliases_everything_p PROTO((rtx));
|
||||
static int write_dependence_p PROTO((rtx, rtx, int));
|
||||
|
||||
/* Set up all info needed to perform alias analysis on memory references. */
|
||||
|
||||
#define SIZE_FOR_MODE(X) (GET_MODE_SIZE (GET_MODE (X)))
|
||||
|
||||
/* Perform a basic sanity check. Namely, that there are
|
||||
no alias sets if we're not doing strict aliasing. This helps
|
||||
to catch bugs whereby someone uses PUT_CODE, but doesn't clear
|
||||
MEM_ALIAS_SET, or where a MEM is allocated in some way other
|
||||
than by the use of gen_rtx_MEM, and the MEM_ALIAS_SET is not
|
||||
cleared. */
|
||||
#ifdef ENABLE_CHECKING
|
||||
#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) \
|
||||
(!flag_strict_aliasing \
|
||||
&& (MEM_ALIAS_SET (MEM1) || MEM_ALIAS_SET (MEM2)) \
|
||||
? (abort (), 0) : 0)
|
||||
#else
|
||||
#define CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2) ((void)0)
|
||||
#endif
|
||||
|
||||
/* Returns nonzero if MEM1 and MEM2 do not alias because they are in
|
||||
different alias sets. */
|
||||
#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
|
||||
(CHECK_ALIAS_SETS_FOR_CONSISTENCY(MEM1, MEM2), \
|
||||
MEM_ALIAS_SET (MEM1) && MEM_ALIAS_SET (MEM2) \
|
||||
&& MEM_ALIAS_SET (MEM1) != MEM_ALIAS_SET (MEM2))
|
||||
different alias sets. We ignore alias sets in functions making use
|
||||
of variable arguments because the va_arg macros on some systems are
|
||||
not legal ANSI C. */
|
||||
#define DIFFERENT_ALIAS_SETS_P(MEM1, MEM2) \
|
||||
mems_in_disjoint_alias_sets_p (MEM1, MEM2)
|
||||
|
||||
/* Cap the number of passes we make over the insns propagating alias
|
||||
information through set chains.
|
||||
@ -89,7 +126,7 @@ rtx *reg_base_value;
|
||||
rtx *new_reg_base_value;
|
||||
unsigned int reg_base_value_size; /* size of reg_base_value array */
|
||||
#define REG_BASE_VALUE(X) \
|
||||
(REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
|
||||
((unsigned) REGNO (X) < reg_base_value_size ? reg_base_value[REGNO (X)] : 0)
|
||||
|
||||
/* Vector of known invariant relationships between registers. Set in
|
||||
loop unrolling. Indexed by register number, if nonzero the value
|
||||
@ -126,6 +163,148 @@ char *reg_known_equiv_p;
|
||||
|
||||
static int copying_arguments;
|
||||
|
||||
/* The splay-tree used to store the various alias set entries. */
|
||||
|
||||
static splay_tree alias_sets;
|
||||
|
||||
/* Returns a pointer to the alias set entry for ALIAS_SET, if there is
|
||||
such an entry, or NULL otherwise. */
|
||||
|
||||
static alias_set_entry
|
||||
get_alias_set_entry (alias_set)
|
||||
int alias_set;
|
||||
{
|
||||
splay_tree_node sn =
|
||||
splay_tree_lookup (alias_sets, (splay_tree_key) alias_set);
|
||||
|
||||
return sn ? ((alias_set_entry) sn->value) : ((alias_set_entry) 0);
|
||||
}
|
||||
|
||||
/* Returns nonzero value if the alias sets for MEM1 and MEM2 are such
|
||||
that the two MEMs cannot alias each other. */
|
||||
|
||||
static int
|
||||
mems_in_disjoint_alias_sets_p (mem1, mem2)
|
||||
rtx mem1;
|
||||
rtx mem2;
|
||||
{
|
||||
alias_set_entry ase;
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
/* Perform a basic sanity check. Namely, that there are no alias sets
|
||||
if we're not using strict aliasing. This helps to catch bugs
|
||||
whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or
|
||||
where a MEM is allocated in some way other than by the use of
|
||||
gen_rtx_MEM, and the MEM_ALIAS_SET is not cleared. If we begin to
|
||||
use alias sets to indicate that spilled registers cannot alias each
|
||||
other, we might need to remove this check. */
|
||||
if (!flag_strict_aliasing &&
|
||||
(MEM_ALIAS_SET (mem1) || MEM_ALIAS_SET (mem2)))
|
||||
abort ();
|
||||
#endif
|
||||
|
||||
/* The code used in varargs macros are often not conforming ANSI C,
|
||||
which can trick the compiler into making incorrect aliasing
|
||||
assumptions in these functions. So, we don't use alias sets in
|
||||
such a function. FIXME: This should be moved into the front-end;
|
||||
it is a language-dependent notion, and there's no reason not to
|
||||
still use these checks to handle globals. */
|
||||
if (current_function_stdarg || current_function_varargs)
|
||||
return 0;
|
||||
|
||||
if (!MEM_ALIAS_SET (mem1) || !MEM_ALIAS_SET (mem2))
|
||||
/* We have no alias set information for one of the MEMs, so we
|
||||
have to assume it can alias anything. */
|
||||
return 0;
|
||||
|
||||
if (MEM_ALIAS_SET (mem1) == MEM_ALIAS_SET (mem2))
|
||||
/* The two alias sets are the same, so they may alias. */
|
||||
return 0;
|
||||
|
||||
/* Iterate through each of the children of the first alias set,
|
||||
comparing it with the second alias set. */
|
||||
ase = get_alias_set_entry (MEM_ALIAS_SET (mem1));
|
||||
if (ase && splay_tree_lookup (ase->children,
|
||||
(splay_tree_key) MEM_ALIAS_SET (mem2)))
|
||||
return 0;
|
||||
|
||||
/* Now do the same, but with the alias sets reversed. */
|
||||
ase = get_alias_set_entry (MEM_ALIAS_SET (mem2));
|
||||
if (ase && splay_tree_lookup (ase->children,
|
||||
(splay_tree_key) MEM_ALIAS_SET (mem1)))
|
||||
return 0;
|
||||
|
||||
/* The two MEMs are in distinct alias sets, and neither one is the
|
||||
child of the other. Therefore, they cannot alias. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Insert the NODE into the splay tree given by DATA. Used by
|
||||
record_alias_subset via splay_tree_foreach. */
|
||||
|
||||
static int
|
||||
insert_subset_children (node, data)
|
||||
splay_tree_node node;
|
||||
void *data;
|
||||
{
|
||||
splay_tree_insert ((splay_tree) data,
|
||||
node->key,
|
||||
node->value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Indicate that things in SUBSET can alias things in SUPERSET, but
|
||||
not vice versa. For example, in C, a store to an `int' can alias a
|
||||
structure containing an `int', but not vice versa. Here, the
|
||||
structure would be the SUPERSET and `int' the SUBSET. This
|
||||
function should be called only once per SUPERSET/SUBSET pair. At
|
||||
present any given alias set may only be a subset of one superset.
|
||||
|
||||
It is illegal for SUPERSET to be zero; everything is implicitly a
|
||||
subset of alias set zero. */
|
||||
|
||||
void
|
||||
record_alias_subset (superset, subset)
|
||||
int superset;
|
||||
int subset;
|
||||
{
|
||||
alias_set_entry superset_entry;
|
||||
alias_set_entry subset_entry;
|
||||
|
||||
if (superset == 0)
|
||||
abort ();
|
||||
|
||||
superset_entry = get_alias_set_entry (superset);
|
||||
if (!superset_entry)
|
||||
{
|
||||
/* Create an entry for the SUPERSET, so that we have a place to
|
||||
attach the SUBSET. */
|
||||
superset_entry =
|
||||
(alias_set_entry) xmalloc (sizeof (struct alias_set_entry));
|
||||
superset_entry->alias_set = superset;
|
||||
superset_entry->children
|
||||
= splay_tree_new (splay_tree_compare_ints, 0, 0);
|
||||
splay_tree_insert (alias_sets,
|
||||
(splay_tree_key) superset,
|
||||
(splay_tree_value) superset_entry);
|
||||
|
||||
}
|
||||
|
||||
subset_entry = get_alias_set_entry (subset);
|
||||
if (subset_entry)
|
||||
/* There is an entry for the subset. Enter all of its children
|
||||
(if they are not already present) as children of the SUPERSET. */
|
||||
splay_tree_foreach (subset_entry->children,
|
||||
insert_subset_children,
|
||||
superset_entry->children);
|
||||
|
||||
/* Enter the SUBSET itself as a child of the SUPERSET. */
|
||||
splay_tree_insert (superset_entry->children,
|
||||
(splay_tree_key) subset,
|
||||
/*value=*/0);
|
||||
}
|
||||
|
||||
/* Inside SRC, the source of a SET, find a base address. */
|
||||
|
||||
static rtx
|
||||
@ -153,7 +332,7 @@ find_base_value (src)
|
||||
The test above is not sufficient because the scheduler may move
|
||||
a copy out of an arg reg past the NOTE_INSN_FUNCTION_BEGIN. */
|
||||
if (REGNO (src) >= FIRST_PSEUDO_REGISTER
|
||||
&& REGNO (src) < reg_base_value_size
|
||||
&& (unsigned) REGNO (src) < reg_base_value_size
|
||||
&& reg_base_value[REGNO (src)])
|
||||
return reg_base_value[REGNO (src)];
|
||||
|
||||
@ -336,7 +515,7 @@ record_base_value (regno, val, invariant)
|
||||
rtx val;
|
||||
int invariant;
|
||||
{
|
||||
if (regno >= reg_base_value_size)
|
||||
if ((unsigned) regno >= reg_base_value_size)
|
||||
return;
|
||||
|
||||
/* If INVARIANT is true then this value also describes an invariant
|
||||
@ -347,7 +526,7 @@ record_base_value (regno, val, invariant)
|
||||
|
||||
if (GET_CODE (val) == REG)
|
||||
{
|
||||
if (REGNO (val) < reg_base_value_size)
|
||||
if ((unsigned) REGNO (val) < reg_base_value_size)
|
||||
{
|
||||
reg_base_value[regno] = reg_base_value[REGNO (val)];
|
||||
}
|
||||
@ -391,9 +570,8 @@ canon_rtx (x)
|
||||
if (addr != XEXP (x, 0))
|
||||
{
|
||||
rtx new = gen_rtx_MEM (GET_MODE (x), addr);
|
||||
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
|
||||
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
|
||||
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
|
||||
MEM_COPY_ATTRIBUTES (new, x);
|
||||
MEM_ALIAS_SET (new) = MEM_ALIAS_SET (x);
|
||||
x = new;
|
||||
}
|
||||
@ -568,10 +746,55 @@ find_base_term (x)
|
||||
case PLUS:
|
||||
case MINUS:
|
||||
{
|
||||
rtx tmp = find_base_term (XEXP (x, 0));
|
||||
if (tmp)
|
||||
return tmp;
|
||||
return find_base_term (XEXP (x, 1));
|
||||
rtx tmp1 = XEXP (x, 0);
|
||||
rtx tmp2 = XEXP (x, 1);
|
||||
|
||||
/* This is a litle bit tricky since we have to determine which of
|
||||
the two operands represents the real base address. Otherwise this
|
||||
routine may return the index register instead of the base register.
|
||||
|
||||
That may cause us to believe no aliasing was possible, when in
|
||||
fact aliasing is possible.
|
||||
|
||||
We use a few simple tests to guess the base register. Additional
|
||||
tests can certainly be added. For example, if one of the operands
|
||||
is a shift or multiply, then it must be the index register and the
|
||||
other operand is the base register. */
|
||||
|
||||
/* If either operand is known to be a pointer, then use it
|
||||
to determine the base term. */
|
||||
if (REG_P (tmp1) && REGNO_POINTER_FLAG (REGNO (tmp1)))
|
||||
return find_base_term (tmp1);
|
||||
|
||||
if (REG_P (tmp2) && REGNO_POINTER_FLAG (REGNO (tmp2)))
|
||||
return find_base_term (tmp2);
|
||||
|
||||
/* Neither operand was known to be a pointer. Go ahead and find the
|
||||
base term for both operands. */
|
||||
tmp1 = find_base_term (tmp1);
|
||||
tmp2 = find_base_term (tmp2);
|
||||
|
||||
/* If either base term is named object or a special address
|
||||
(like an argument or stack reference), then use it for the
|
||||
base term. */
|
||||
if (tmp1
|
||||
&& (GET_CODE (tmp1) == SYMBOL_REF
|
||||
|| GET_CODE (tmp1) == LABEL_REF
|
||||
|| (GET_CODE (tmp1) == ADDRESS
|
||||
&& GET_MODE (tmp1) != VOIDmode)))
|
||||
return tmp1;
|
||||
|
||||
if (tmp2
|
||||
&& (GET_CODE (tmp2) == SYMBOL_REF
|
||||
|| GET_CODE (tmp2) == LABEL_REF
|
||||
|| (GET_CODE (tmp2) == ADDRESS
|
||||
&& GET_MODE (tmp2) != VOIDmode)))
|
||||
return tmp2;
|
||||
|
||||
/* We could not determine which of the two operands was the
|
||||
base register and which was the index. So we can determine
|
||||
nothing from the base alias check. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
case AND:
|
||||
@ -592,8 +815,9 @@ find_base_term (x)
|
||||
objects, 1 if they might be pointers to the same object. */
|
||||
|
||||
static int
|
||||
base_alias_check (x, y)
|
||||
base_alias_check (x, y, x_mode, y_mode)
|
||||
rtx x, y;
|
||||
enum machine_mode x_mode, y_mode;
|
||||
{
|
||||
rtx x_base = find_base_term (x);
|
||||
rtx y_base = find_base_term (y);
|
||||
@ -625,17 +849,25 @@ base_alias_check (x, y)
|
||||
if (rtx_equal_p (x_base, y_base))
|
||||
return 1;
|
||||
|
||||
/* The base addresses of the read and write are different
|
||||
expressions. If they are both symbols and they are not accessed
|
||||
via AND, there is no conflict. */
|
||||
/* XXX: We can bring knowledge of object alignment and offset into
|
||||
play here. For example, on alpha, "char a, b;" can alias one
|
||||
another, though "char a; long b;" cannot. Similarly, offsets
|
||||
into strutures may be brought into play. Given "char a, b[40];",
|
||||
a and b[1] may overlap, but a and b[20] do not. */
|
||||
/* The base addresses of the read and write are different expressions.
|
||||
If they are both symbols and they are not accessed via AND, there is
|
||||
no conflict. We can bring knowledge of object alignment into play
|
||||
here. For example, on alpha, "char a, b;" can alias one another,
|
||||
though "char a; long b;" cannot. */
|
||||
if (GET_CODE (x_base) != ADDRESS && GET_CODE (y_base) != ADDRESS)
|
||||
{
|
||||
return GET_CODE (x) == AND || GET_CODE (y) == AND;
|
||||
if (GET_CODE (x) == AND && GET_CODE (y) == AND)
|
||||
return 1;
|
||||
if (GET_CODE (x) == AND
|
||||
&& (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
|| GET_MODE_UNIT_SIZE (y_mode) < -INTVAL (XEXP (x, 1))))
|
||||
return 1;
|
||||
if (GET_CODE (y) == AND
|
||||
&& (GET_CODE (XEXP (y, 1)) != CONST_INT
|
||||
|| GET_MODE_UNIT_SIZE (x_mode) < -INTVAL (XEXP (y, 1))))
|
||||
return 1;
|
||||
/* Differing symbols never alias. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If one address is a stack reference there can be no alias:
|
||||
@ -656,6 +888,45 @@ base_alias_check (x, y)
|
||||
return ! (GET_MODE (x_base) == VOIDmode && GET_MODE (y_base) == VOIDmode);
|
||||
}
|
||||
|
||||
/* Return the address of the (N_REFS + 1)th memory reference to ADDR
|
||||
where SIZE is the size in bytes of the memory reference. If ADDR
|
||||
is not modified by the memory reference then ADDR is returned. */
|
||||
|
||||
rtx
|
||||
addr_side_effect_eval (addr, size, n_refs)
|
||||
rtx addr;
|
||||
int size;
|
||||
int n_refs;
|
||||
{
|
||||
int offset = 0;
|
||||
|
||||
switch (GET_CODE (addr))
|
||||
{
|
||||
case PRE_INC:
|
||||
offset = (n_refs + 1) * size;
|
||||
break;
|
||||
case PRE_DEC:
|
||||
offset = -(n_refs + 1) * size;
|
||||
break;
|
||||
case POST_INC:
|
||||
offset = n_refs * size;
|
||||
break;
|
||||
case POST_DEC:
|
||||
offset = -n_refs * size;
|
||||
break;
|
||||
|
||||
default:
|
||||
return addr;
|
||||
}
|
||||
|
||||
if (offset)
|
||||
addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0), GEN_INT (offset));
|
||||
else
|
||||
addr = XEXP (addr, 0);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* Return nonzero if X and Y (memory addresses) could reference the
|
||||
same location in memory. C is an offset accumulator. When
|
||||
C is nonzero, we are testing aliases between X and Y + C.
|
||||
@ -685,13 +956,13 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
|
||||
else if (GET_CODE (x) == LO_SUM)
|
||||
x = XEXP (x, 1);
|
||||
else
|
||||
x = canon_rtx (x);
|
||||
x = canon_rtx (addr_side_effect_eval (x, xsize, 0));
|
||||
if (GET_CODE (y) == HIGH)
|
||||
y = XEXP (y, 0);
|
||||
else if (GET_CODE (y) == LO_SUM)
|
||||
y = XEXP (y, 1);
|
||||
else
|
||||
y = canon_rtx (y);
|
||||
y = canon_rtx (addr_side_effect_eval (y, ysize, 0));
|
||||
|
||||
if (rtx_equal_for_memref_p (x, y))
|
||||
{
|
||||
@ -726,11 +997,14 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
|
||||
if (rtx_equal_for_memref_p (x0, y0))
|
||||
return memrefs_conflict_p (xsize, x1, ysize, y1, c);
|
||||
if (GET_CODE (x1) == CONST_INT)
|
||||
if (GET_CODE (y1) == CONST_INT)
|
||||
return memrefs_conflict_p (xsize, x0, ysize, y0,
|
||||
c - INTVAL (x1) + INTVAL (y1));
|
||||
else
|
||||
return memrefs_conflict_p (xsize, x0, ysize, y, c - INTVAL (x1));
|
||||
{
|
||||
if (GET_CODE (y1) == CONST_INT)
|
||||
return memrefs_conflict_p (xsize, x0, ysize, y0,
|
||||
c - INTVAL (x1) + INTVAL (y1));
|
||||
else
|
||||
return memrefs_conflict_p (xsize, x0, ysize, y,
|
||||
c - INTVAL (x1));
|
||||
}
|
||||
else if (GET_CODE (y1) == CONST_INT)
|
||||
return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1));
|
||||
|
||||
@ -784,7 +1058,7 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
|
||||
/* Are these registers known not to be equal? */
|
||||
if (alias_invariant)
|
||||
{
|
||||
int r_x = REGNO (x), r_y = REGNO (y);
|
||||
unsigned int r_x = REGNO (x), r_y = REGNO (y);
|
||||
rtx i_x, i_y; /* invariant relationships of X and Y */
|
||||
|
||||
i_x = r_x >= reg_base_value_size ? 0 : alias_invariant[r_x];
|
||||
@ -804,18 +1078,24 @@ memrefs_conflict_p (xsize, x, ysize, y, c)
|
||||
}
|
||||
|
||||
/* Treat an access through an AND (e.g. a subword access on an Alpha)
|
||||
as an access with indeterminate size.
|
||||
??? Could instead convert an n byte reference at (and x y) to an
|
||||
n-y byte reference at (plus x y). */
|
||||
as an access with indeterminate size. Assume that references
|
||||
besides AND are aligned, so if the size of the other reference is
|
||||
at least as large as the alignment, assume no other overlap. */
|
||||
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT)
|
||||
return memrefs_conflict_p (-1, XEXP (x, 0), ysize, y, c);
|
||||
{
|
||||
if (GET_CODE (y) == AND || ysize < -INTVAL (XEXP (x, 1)))
|
||||
xsize = -1;
|
||||
return memrefs_conflict_p (xsize, XEXP (x, 0), ysize, y, c);
|
||||
}
|
||||
if (GET_CODE (y) == AND && GET_CODE (XEXP (y, 1)) == CONST_INT)
|
||||
{
|
||||
/* XXX: If we are indexing far enough into the array/structure, we
|
||||
/* ??? If we are indexing far enough into the array/structure, we
|
||||
may yet be able to determine that we can not overlap. But we
|
||||
also need to that we are far enough from the end not to overlap
|
||||
a following reference, so we do nothing for now. */
|
||||
return memrefs_conflict_p (xsize, x, -1, XEXP (y, 0), c);
|
||||
a following reference, so we do nothing with that for now. */
|
||||
if (GET_CODE (x) == AND || xsize < -INTVAL (XEXP (y, 1)))
|
||||
ysize = -1;
|
||||
return memrefs_conflict_p (xsize, x, ysize, XEXP (y, 0), c);
|
||||
}
|
||||
|
||||
if (CONSTANT_P (x))
|
||||
@ -883,6 +1163,56 @@ read_dependence (mem, x)
|
||||
return MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem);
|
||||
}
|
||||
|
||||
/* Returns MEM1 if and only if MEM1 is a scalar at a fixed address and
|
||||
MEM2 is a reference to a structure at a varying address, or returns
|
||||
MEM2 if vice versa. Otherwise, returns NULL_RTX. If a non-NULL
|
||||
value is returned MEM1 and MEM2 can never alias. VARIES_P is used
|
||||
to decide whether or not an address may vary; it should return
|
||||
nozero whenever variation is possible. */
|
||||
|
||||
static rtx
|
||||
fixed_scalar_and_varying_struct_p (mem1, mem2, varies_p)
|
||||
rtx mem1;
|
||||
rtx mem2;
|
||||
int (*varies_p) PROTO((rtx));
|
||||
{
|
||||
rtx mem1_addr = XEXP (mem1, 0);
|
||||
rtx mem2_addr = XEXP (mem2, 0);
|
||||
|
||||
if (MEM_SCALAR_P (mem1) && MEM_IN_STRUCT_P (mem2)
|
||||
&& !varies_p (mem1_addr) && varies_p (mem2_addr))
|
||||
/* MEM1 is a scalar at a fixed address; MEM2 is a struct at a
|
||||
varying address. */
|
||||
return mem1;
|
||||
|
||||
if (MEM_IN_STRUCT_P (mem1) && MEM_SCALAR_P (mem2)
|
||||
&& varies_p (mem1_addr) && !varies_p (mem2_addr))
|
||||
/* MEM2 is a scalar at a fixed address; MEM1 is a struct at a
|
||||
varying address. */
|
||||
return mem2;
|
||||
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Returns nonzero if something about the mode or address format MEM1
|
||||
indicates that it might well alias *anything*. */
|
||||
|
||||
static int
|
||||
aliases_everything_p (mem)
|
||||
rtx mem;
|
||||
{
|
||||
if (GET_MODE (mem) == QImode)
|
||||
/* ANSI C says that a `char*' can point to anything. */
|
||||
return 1;
|
||||
|
||||
if (GET_CODE (XEXP (mem, 0)) == AND)
|
||||
/* If the address is an AND, its very hard to know at what it is
|
||||
actually pointing. */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* True dependence: X is read after store in MEM takes place. */
|
||||
|
||||
int
|
||||
@ -910,59 +1240,46 @@ true_dependence (mem, mem_mode, x, varies)
|
||||
if (RTX_UNCHANGING_P (x) && ! RTX_UNCHANGING_P (mem))
|
||||
return 0;
|
||||
|
||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
|
||||
if (mem_mode == VOIDmode)
|
||||
mem_mode = GET_MODE (mem);
|
||||
|
||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x), mem_mode))
|
||||
return 0;
|
||||
|
||||
x_addr = canon_rtx (XEXP (x, 0));
|
||||
mem_addr = canon_rtx (XEXP (mem, 0));
|
||||
|
||||
if (mem_mode == VOIDmode)
|
||||
mem_mode = GET_MODE (mem);
|
||||
|
||||
if (! memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr,
|
||||
SIZE_FOR_MODE (x), x_addr, 0))
|
||||
return 0;
|
||||
|
||||
/* If both references are struct references, or both are not, nothing
|
||||
is known about aliasing.
|
||||
|
||||
If either reference is QImode or BLKmode, ANSI C permits aliasing.
|
||||
|
||||
If both addresses are constant, or both are not, nothing is known
|
||||
about aliasing. */
|
||||
if (MEM_IN_STRUCT_P (x) == MEM_IN_STRUCT_P (mem)
|
||||
|| mem_mode == QImode || mem_mode == BLKmode
|
||||
|| GET_MODE (x) == QImode || GET_MODE (x) == BLKmode
|
||||
|| GET_CODE (x_addr) == AND || GET_CODE (mem_addr) == AND
|
||||
|| varies (x_addr) == varies (mem_addr))
|
||||
if (aliases_everything_p (x))
|
||||
return 1;
|
||||
|
||||
/* One memory reference is to a constant address, one is not.
|
||||
One is to a structure, the other is not.
|
||||
/* We cannot use aliases_everyting_p to test MEM, since we must look
|
||||
at MEM_MODE, rather than GET_MODE (MEM). */
|
||||
if (mem_mode == QImode || GET_CODE (mem_addr) == AND)
|
||||
return 1;
|
||||
|
||||
If either memory reference is a variable structure the other is a
|
||||
fixed scalar and there is no aliasing. */
|
||||
/* In true_dependence we also allow BLKmode to alias anything. Why
|
||||
don't we do this in anti_dependence and output_dependence? */
|
||||
if (mem_mode == BLKmode || GET_MODE (x) == BLKmode)
|
||||
return 1;
|
||||
|
||||
/* Disabled by default for egcs 1.1.x as alias analysis isn't good
|
||||
enough yet to discover all cases where this doesn't apply. */
|
||||
if (flag_structure_noalias)
|
||||
{
|
||||
if ((MEM_IN_STRUCT_P (mem) && varies (mem_addr))
|
||||
|| (MEM_IN_STRUCT_P (x) && varies (x_addr)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
return !fixed_scalar_and_varying_struct_p (mem, x, varies);
|
||||
}
|
||||
|
||||
/* Anti dependence: X is written after read in MEM takes place. */
|
||||
/* Returns non-zero if a write to X might alias a previous read from
|
||||
(or, if WRITEP is non-zero, a write to) MEM. */
|
||||
|
||||
int
|
||||
anti_dependence (mem, x)
|
||||
static int
|
||||
write_dependence_p (mem, x, writep)
|
||||
rtx mem;
|
||||
rtx x;
|
||||
int writep;
|
||||
{
|
||||
rtx x_addr, mem_addr;
|
||||
rtx fixed_scalar;
|
||||
|
||||
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
|
||||
return 1;
|
||||
@ -970,10 +1287,11 @@ anti_dependence (mem, x)
|
||||
/* If MEM is an unchanging read, then it can't possibly conflict with
|
||||
the store to X, because there is at most one store to MEM, and it must
|
||||
have occurred somewhere before MEM. */
|
||||
if (RTX_UNCHANGING_P (mem))
|
||||
if (!writep && RTX_UNCHANGING_P (mem))
|
||||
return 0;
|
||||
|
||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
|
||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0), GET_MODE (x),
|
||||
GET_MODE (mem)))
|
||||
return 0;
|
||||
|
||||
x = canon_rtx (x);
|
||||
@ -985,16 +1303,25 @@ anti_dependence (mem, x)
|
||||
x_addr = XEXP (x, 0);
|
||||
mem_addr = XEXP (mem, 0);
|
||||
|
||||
return (memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
|
||||
SIZE_FOR_MODE (x), x_addr, 0)
|
||||
&& ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
|
||||
&& GET_MODE (mem) != QImode
|
||||
&& GET_CODE (mem_addr) != AND
|
||||
&& ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
|
||||
&& ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
|
||||
&& GET_MODE (x) != QImode
|
||||
&& GET_CODE (x_addr) != AND
|
||||
&& ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
|
||||
if (!memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr,
|
||||
SIZE_FOR_MODE (x), x_addr, 0))
|
||||
return 0;
|
||||
|
||||
fixed_scalar
|
||||
= fixed_scalar_and_varying_struct_p (mem, x, rtx_addr_varies_p);
|
||||
|
||||
return (!(fixed_scalar == mem && !aliases_everything_p (x))
|
||||
&& !(fixed_scalar == x && !aliases_everything_p (mem)));
|
||||
}
|
||||
|
||||
/* Anti dependence: X is written after read in MEM takes place. */
|
||||
|
||||
int
|
||||
anti_dependence (mem, x)
|
||||
rtx mem;
|
||||
rtx x;
|
||||
{
|
||||
return write_dependence_p (mem, x, /*writep=*/0);
|
||||
}
|
||||
|
||||
/* Output dependence: X is written after store in MEM takes place. */
|
||||
@ -1004,28 +1331,7 @@ output_dependence (mem, x)
|
||||
register rtx mem;
|
||||
register rtx x;
|
||||
{
|
||||
if (MEM_VOLATILE_P (x) && MEM_VOLATILE_P (mem))
|
||||
return 1;
|
||||
|
||||
if (! base_alias_check (XEXP (x, 0), XEXP (mem, 0)))
|
||||
return 0;
|
||||
|
||||
x = canon_rtx (x);
|
||||
mem = canon_rtx (mem);
|
||||
|
||||
if (DIFFERENT_ALIAS_SETS_P (x, mem))
|
||||
return 0;
|
||||
|
||||
return (memrefs_conflict_p (SIZE_FOR_MODE (mem), XEXP (mem, 0),
|
||||
SIZE_FOR_MODE (x), XEXP (x, 0), 0)
|
||||
&& ! (MEM_IN_STRUCT_P (mem) && rtx_addr_varies_p (mem)
|
||||
&& GET_MODE (mem) != QImode
|
||||
&& GET_CODE (XEXP (mem, 0)) != AND
|
||||
&& ! MEM_IN_STRUCT_P (x) && ! rtx_addr_varies_p (x))
|
||||
&& ! (MEM_IN_STRUCT_P (x) && rtx_addr_varies_p (x)
|
||||
&& GET_MODE (x) != QImode
|
||||
&& GET_CODE (XEXP (x, 0)) != AND
|
||||
&& ! MEM_IN_STRUCT_P (mem) && ! rtx_addr_varies_p (mem)));
|
||||
return write_dependence_p (mem, x, /*writep=*/1);
|
||||
}
|
||||
|
||||
|
||||
@ -1046,6 +1352,8 @@ init_alias_once ()
|
||||
if (FUNCTION_ARG_REGNO_P (OUTGOING_REGNO (i))
|
||||
&& HARD_REGNO_MODE_OK (i, Pmode))
|
||||
SET_HARD_REG_BIT (argument_registers, i);
|
||||
|
||||
alias_sets = splay_tree_new (splay_tree_compare_ints, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1054,6 +1362,7 @@ init_alias_analysis ()
|
||||
int maxreg = max_reg_num ();
|
||||
int changed, pass;
|
||||
register int i;
|
||||
register unsigned int ui;
|
||||
register rtx insn;
|
||||
|
||||
reg_known_value_size = maxreg;
|
||||
@ -1194,13 +1503,13 @@ init_alias_analysis ()
|
||||
}
|
||||
|
||||
/* Now propagate values from new_reg_base_value to reg_base_value. */
|
||||
for (i = 0; i < reg_base_value_size; i++)
|
||||
for (ui = 0; ui < reg_base_value_size; ui++)
|
||||
{
|
||||
if (new_reg_base_value[i]
|
||||
&& new_reg_base_value[i] != reg_base_value[i]
|
||||
&& ! rtx_equal_p (new_reg_base_value[i], reg_base_value[i]))
|
||||
if (new_reg_base_value[ui]
|
||||
&& new_reg_base_value[ui] != reg_base_value[ui]
|
||||
&& ! rtx_equal_p (new_reg_base_value[ui], reg_base_value[ui]))
|
||||
{
|
||||
reg_base_value[i] = new_reg_base_value[i];
|
||||
reg_base_value[ui] = new_reg_base_value[ui];
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
@ -1227,16 +1536,16 @@ init_alias_analysis ()
|
||||
{
|
||||
changed = 0;
|
||||
pass++;
|
||||
for (i = 0; i < reg_base_value_size; i++)
|
||||
for (ui = 0; ui < reg_base_value_size; ui++)
|
||||
{
|
||||
rtx base = reg_base_value[i];
|
||||
rtx base = reg_base_value[ui];
|
||||
if (base && GET_CODE (base) == REG)
|
||||
{
|
||||
int base_regno = REGNO (base);
|
||||
if (base_regno == i) /* register set from itself */
|
||||
reg_base_value[i] = 0;
|
||||
unsigned int base_regno = REGNO (base);
|
||||
if (base_regno == ui) /* register set from itself */
|
||||
reg_base_value[ui] = 0;
|
||||
else
|
||||
reg_base_value[i] = reg_base_value[base_regno];
|
||||
reg_base_value[ui] = reg_base_value[base_regno];
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define control and data flow tables, and regsets.
|
||||
Copyright (C) 1987, 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "sbitmap.h"
|
||||
#include "varray.h"
|
||||
|
||||
typedef bitmap regset; /* Head of register set linked list. */
|
||||
|
||||
@ -94,29 +96,65 @@ do { \
|
||||
/* Grow any tables needed when the number of registers is calculated
|
||||
or extended. For the linked list allocation, nothing needs to
|
||||
be done, other than zero the statistics on the first allocation. */
|
||||
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
|
||||
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
|
||||
|
||||
/* Control flow edge information. */
|
||||
typedef struct edge_def {
|
||||
/* Links through the predecessor and successor lists. */
|
||||
struct edge_def *pred_next, *succ_next;
|
||||
|
||||
/* The two blocks at the ends of the edge. */
|
||||
struct basic_block_def *src, *dest;
|
||||
|
||||
/* Instructions queued on the edge. */
|
||||
rtx insns;
|
||||
|
||||
/* Auxiliary info specific to a pass. */
|
||||
void *aux;
|
||||
|
||||
int flags; /* see EDGE_* below */
|
||||
int probability; /* biased by REG_BR_PROB_BASE */
|
||||
} *edge;
|
||||
|
||||
#define EDGE_FALLTHRU 1
|
||||
#define EDGE_CRITICAL 2
|
||||
#define EDGE_ABNORMAL 4
|
||||
#define EDGE_ABNORMAL_CALL 8
|
||||
#define EDGE_EH 16
|
||||
#define EDGE_FAKE 32
|
||||
|
||||
|
||||
/* Basic block information indexed by block number. */
|
||||
typedef struct basic_block_def {
|
||||
/* The first and last insns of the block. */
|
||||
rtx head, end;
|
||||
|
||||
/* The edges into and out of the block. */
|
||||
edge pred, succ;
|
||||
|
||||
/* Liveness info. */
|
||||
regset local_set;
|
||||
regset global_live_at_start;
|
||||
regset global_live_at_end;
|
||||
|
||||
/* Auxiliary info specific to a pass. */
|
||||
void *aux;
|
||||
|
||||
/* The index of this block. */
|
||||
int index;
|
||||
/* The loop depth of this block plus one. */
|
||||
int loop_depth;
|
||||
} *basic_block;
|
||||
|
||||
/* Number of basic blocks in the current function. */
|
||||
|
||||
extern int n_basic_blocks;
|
||||
|
||||
/* Index by basic block number, get first insn in the block. */
|
||||
/* Index by basic block number, get basic block struct info. */
|
||||
|
||||
extern rtx *basic_block_head;
|
||||
extern varray_type basic_block_info;
|
||||
|
||||
/* Index by basic block number, get last insn in the block. */
|
||||
|
||||
extern rtx *basic_block_end;
|
||||
|
||||
/* Index by basic block number, determine whether the block can be reached
|
||||
through a computed jump. */
|
||||
|
||||
extern char *basic_block_computed_jump_target;
|
||||
|
||||
/* Index by basic block number, get address of regset
|
||||
describing the registers live at the start of that block. */
|
||||
|
||||
extern regset *basic_block_live_at_start;
|
||||
#define BASIC_BLOCK(N) (VARRAY_BB (basic_block_info, (N)))
|
||||
|
||||
/* What registers are live at the setjmp call. */
|
||||
|
||||
@ -176,91 +214,49 @@ extern void free_int_list PROTO ((int_list_block **));
|
||||
|
||||
/* Stuff for recording basic block info. */
|
||||
|
||||
#define BLOCK_HEAD(B) basic_block_head[(B)]
|
||||
#define BLOCK_END(B) basic_block_end[(B)]
|
||||
#define BLOCK_HEAD(B) (BASIC_BLOCK (B)->head)
|
||||
#define BLOCK_END(B) (BASIC_BLOCK (B)->end)
|
||||
|
||||
/* Special block numbers [markers] for entry and exit. */
|
||||
#define ENTRY_BLOCK (-1)
|
||||
#define EXIT_BLOCK (-2)
|
||||
|
||||
/* from flow.c */
|
||||
extern void free_regset_vector PROTO ((regset *, int nelts));
|
||||
extern int *uid_block_number;
|
||||
#define BLOCK_NUM(INSN) uid_block_number[INSN_UID (INSN)]
|
||||
/* Similarly, block pointers for the edge list. */
|
||||
extern struct basic_block_def entry_exit_blocks[2];
|
||||
#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
|
||||
#define EXIT_BLOCK_PTR (&entry_exit_blocks[1])
|
||||
|
||||
extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
|
||||
int *, int *));
|
||||
extern void dump_bb_data PROTO ((FILE *, int_list_ptr *, int_list_ptr *));
|
||||
extern void free_bb_mem PROTO ((void));
|
||||
/* from flow.c */
|
||||
extern void free_regset_vector PROTO ((regset *, int nelts));
|
||||
|
||||
extern varray_type basic_block_for_insn;
|
||||
#define BLOCK_FOR_INSN(INSN) VARRAY_BB (basic_block_for_insn, INSN_UID (INSN))
|
||||
#define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0)
|
||||
|
||||
extern void set_block_for_insn PROTO ((rtx, basic_block));
|
||||
|
||||
extern void dump_bb_data PROTO ((FILE *, int_list_ptr *,
|
||||
int_list_ptr *, int));
|
||||
extern void free_bb_mem PROTO ((void));
|
||||
extern void free_basic_block_vars PROTO ((int));
|
||||
|
||||
|
||||
/* Simple bitmaps.
|
||||
It's not clear yet whether using bitmap.[ch] will be a win.
|
||||
It should be straightforward to convert so for now we keep things simple
|
||||
while more important issues are dealt with. */
|
||||
extern basic_block split_edge PROTO ((edge));
|
||||
extern void insert_insn_on_edge PROTO ((rtx, edge));
|
||||
extern void commit_edge_insertions PROTO ((void));
|
||||
|
||||
#define SBITMAP_ELT_BITS HOST_BITS_PER_WIDE_INT
|
||||
#define SBITMAP_ELT_TYPE unsigned HOST_WIDE_INT
|
||||
|
||||
typedef struct simple_bitmap_def {
|
||||
/* Number of bits. */
|
||||
int n_bits;
|
||||
/* Size in elements. */
|
||||
int size;
|
||||
/* Size in bytes. */
|
||||
int bytes;
|
||||
/* The elements. */
|
||||
SBITMAP_ELT_TYPE elms[1];
|
||||
} *sbitmap;
|
||||
|
||||
typedef SBITMAP_ELT_TYPE *sbitmap_ptr;
|
||||
|
||||
/* Return the set size needed for N elements. */
|
||||
#define SBITMAP_SET_SIZE(n) (((n) + SBITMAP_ELT_BITS - 1) / SBITMAP_ELT_BITS)
|
||||
|
||||
/* set bit number bitno in the bitmap */
|
||||
#define SET_BIT(bitmap, bitno) \
|
||||
do { \
|
||||
(bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] |= (SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS; \
|
||||
} while (0)
|
||||
|
||||
/* test if bit number bitno in the bitmap is set */
|
||||
#define TEST_BIT(bitmap, bitno) \
|
||||
((bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] & ((SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS))
|
||||
|
||||
/* reset bit number bitno in the bitmap */
|
||||
#define RESET_BIT(bitmap, bitno) \
|
||||
do { \
|
||||
(bitmap)->elms [(bitno) / SBITMAP_ELT_BITS] &= ~((SBITMAP_ELT_TYPE) 1 << (bitno) % SBITMAP_ELT_BITS); \
|
||||
} while (0)
|
||||
|
||||
extern void dump_sbitmap PROTO ((FILE *, sbitmap));
|
||||
extern void dump_sbitmap_vector PROTO ((FILE *, char *, char *,
|
||||
sbitmap *, int));
|
||||
extern sbitmap sbitmap_alloc PROTO ((int));
|
||||
extern sbitmap *sbitmap_vector_alloc PROTO ((int, int));
|
||||
extern void sbitmap_copy PROTO ((sbitmap, sbitmap));
|
||||
extern void sbitmap_zero PROTO ((sbitmap));
|
||||
extern void sbitmap_ones PROTO ((sbitmap));
|
||||
extern void sbitmap_vector_zero PROTO ((sbitmap *, int));
|
||||
extern void sbitmap_vector_ones PROTO ((sbitmap *, int));
|
||||
extern int sbitmap_union_of_diff PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
|
||||
extern void sbitmap_difference PROTO ((sbitmap, sbitmap, sbitmap));
|
||||
extern void sbitmap_not PROTO ((sbitmap, sbitmap));
|
||||
extern int sbitmap_a_or_b_and_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
|
||||
extern int sbitmap_a_and_b_or_c PROTO ((sbitmap, sbitmap, sbitmap, sbitmap));
|
||||
extern int sbitmap_a_and_b PROTO ((sbitmap, sbitmap, sbitmap));
|
||||
extern int sbitmap_a_or_b PROTO ((sbitmap, sbitmap, sbitmap));
|
||||
extern void sbitmap_intersect_of_predsucc PROTO ((sbitmap, sbitmap *,
|
||||
int, int_list_ptr *));
|
||||
extern void sbitmap_intersect_of_predecessors PROTO ((sbitmap, sbitmap *, int,
|
||||
int_list_ptr *));
|
||||
extern void sbitmap_intersect_of_successors PROTO ((sbitmap, sbitmap *, int,
|
||||
int_list_ptr *));
|
||||
extern void sbitmap_union_of_predecessors PROTO ((sbitmap, sbitmap *, int,
|
||||
int_list_ptr *));
|
||||
extern void sbitmap_union_of_successors PROTO ((sbitmap, sbitmap *, int,
|
||||
extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
|
||||
int *, int *));
|
||||
extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
|
||||
int_list_ptr *,
|
||||
int_list_ptr *));
|
||||
extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
|
||||
int_list_ptr *, int_list_ptr *));
|
||||
extern void compute_immediate_dominators PROTO ((int *, sbitmap *));
|
||||
|
||||
/* In lcm.c */
|
||||
extern void pre_lcm PROTO ((int, int, int_list_ptr *,
|
||||
int_list_ptr *,
|
||||
sbitmap *, sbitmap *,
|
||||
sbitmap *, sbitmap *));
|
||||
extern void pre_rev_lcm PROTO ((int, int, int_list_ptr *,
|
||||
int_list_ptr *,
|
||||
sbitmap *, sbitmap *,
|
||||
sbitmap *, sbitmap *));
|
||||
|
@ -613,10 +613,10 @@ void
|
||||
bitmap_print (file, head, prefix, suffix)
|
||||
FILE *file;
|
||||
bitmap head;
|
||||
char *prefix;
|
||||
char *suffix;
|
||||
const char *prefix;
|
||||
const char *suffix;
|
||||
{
|
||||
char *comma = "";
|
||||
const char *comma = "";
|
||||
int i;
|
||||
|
||||
fputs (prefix, file);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Functions to support general ended bitmaps.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -48,7 +48,7 @@ typedef struct bitmap_element_def
|
||||
typedef struct bitmap_head_def {
|
||||
bitmap_element *first; /* First element in linked list. */
|
||||
bitmap_element *current; /* Last element looked at. */
|
||||
int indx; /* Index of last element looked at. */
|
||||
unsigned int indx; /* Index of last element looked at. */
|
||||
} bitmap_head, *bitmap;
|
||||
|
||||
/* Enumeration giving the various operations we support. */
|
||||
@ -89,7 +89,7 @@ extern void bitmap_debug PROTO((bitmap));
|
||||
extern void bitmap_debug_file PROTO((FILE *, bitmap));
|
||||
|
||||
/* Print a bitmap */
|
||||
extern void bitmap_print PROTO((FILE *, bitmap, char *, char *));
|
||||
extern void bitmap_print PROTO((FILE *, bitmap, const char *, const char *));
|
||||
|
||||
/* Initialize a bitmap header. */
|
||||
extern bitmap bitmap_initialize PROTO((bitmap));
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* Generate information regarding function declarations and definitions based
|
||||
on information stored in GCC's tree structure. This code implements the
|
||||
-aux-info option.
|
||||
Copyright (C) 1989, 91, 94, 95, 97, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1989, 91, 94, 95, 97-98, 1999 Free Software Foundation, Inc.
|
||||
Contributed by Ron Guilmette (rfg@segfault.us.com).
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "toplev.h"
|
||||
#include "flags.h"
|
||||
#include "tree.h"
|
||||
#include "c-tree.h"
|
||||
@ -35,67 +36,75 @@ enum formals_style_enum {
|
||||
typedef enum formals_style_enum formals_style;
|
||||
|
||||
|
||||
static char *data_type;
|
||||
static const char *data_type;
|
||||
|
||||
static char *concat PROTO((char *, char *));
|
||||
static char *concat3 PROTO((char *, char *, char *));
|
||||
static char *affix_data_type PROTO((char *));
|
||||
static char *gen_formal_list_for_type PROTO((tree, formals_style));
|
||||
static char *affix_data_type PROTO((const char *));
|
||||
static const char *gen_formal_list_for_type PROTO((tree, formals_style));
|
||||
static int deserves_ellipsis PROTO((tree));
|
||||
static char *gen_formal_list_for_func_def PROTO((tree, formals_style));
|
||||
static char *gen_type PROTO((char *, tree, formals_style));
|
||||
static char *gen_decl PROTO((tree, int, formals_style));
|
||||
static const char *gen_formal_list_for_func_def PROTO((tree, formals_style));
|
||||
static const char *gen_type PROTO((const char *, tree, formals_style));
|
||||
static const char *gen_decl PROTO((tree, int, formals_style));
|
||||
|
||||
/* Take two strings and mash them together into a newly allocated area. */
|
||||
/* Concatenate a sequence of strings, returning the result.
|
||||
|
||||
static char *
|
||||
concat (s1, s2)
|
||||
char *s1;
|
||||
char *s2;
|
||||
This function is based on the one in libiberty. */
|
||||
|
||||
/* This definition will conflict with the one from prefix.c in
|
||||
libcpp.a when linking cc1 and cc1obj. So only provide it if we are
|
||||
not using libcpp.a */
|
||||
#ifndef USE_CPPLIB
|
||||
char *
|
||||
concat VPROTO((const char *first, ...))
|
||||
{
|
||||
int size1, size2;
|
||||
char *ret_val;
|
||||
register int length;
|
||||
register char *newstr;
|
||||
register char *end;
|
||||
register const char *arg;
|
||||
va_list args;
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
const char *first;
|
||||
#endif
|
||||
|
||||
if (!s1)
|
||||
s1 = "";
|
||||
if (!s2)
|
||||
s2 = "";
|
||||
/* First compute the size of the result and get sufficient memory. */
|
||||
|
||||
size1 = strlen (s1);
|
||||
size2 = strlen (s2);
|
||||
ret_val = xmalloc (size1 + size2 + 1);
|
||||
strcpy (ret_val, s1);
|
||||
strcpy (&ret_val[size1], s2);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* Take three strings and mash them together into a newly allocated area. */
|
||||
|
||||
static char *
|
||||
concat3 (s1, s2, s3)
|
||||
char *s1;
|
||||
char *s2;
|
||||
char *s3;
|
||||
{
|
||||
int size1, size2, size3;
|
||||
char *ret_val;
|
||||
|
||||
if (!s1)
|
||||
s1 = "";
|
||||
if (!s2)
|
||||
s2 = "";
|
||||
if (!s3)
|
||||
s3 = "";
|
||||
|
||||
size1 = strlen (s1);
|
||||
size2 = strlen (s2);
|
||||
size3 = strlen (s3);
|
||||
ret_val = xmalloc (size1 + size2 + size3 + 1);
|
||||
strcpy (ret_val, s1);
|
||||
strcpy (&ret_val[size1], s2);
|
||||
strcpy (&ret_val[size1+size2], s3);
|
||||
return ret_val;
|
||||
VA_START (args, first);
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
first = va_arg (args, const char *);
|
||||
#endif
|
||||
|
||||
arg = first;
|
||||
length = 0;
|
||||
|
||||
while (arg != 0)
|
||||
{
|
||||
length += strlen (arg);
|
||||
arg = va_arg (args, const char *);
|
||||
}
|
||||
|
||||
newstr = (char *) malloc (length + 1);
|
||||
va_end (args);
|
||||
|
||||
/* Now copy the individual pieces to the result string. */
|
||||
|
||||
VA_START (args, first);
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
first = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
end = newstr;
|
||||
arg = first;
|
||||
while (arg != 0)
|
||||
{
|
||||
while (*arg)
|
||||
*end++ = *arg++;
|
||||
arg = va_arg (args, const char *);
|
||||
}
|
||||
*end = '\000';
|
||||
va_end (args);
|
||||
|
||||
return (newstr);
|
||||
}
|
||||
#endif /* ! USE_CPPLIB */
|
||||
|
||||
/* Given a string representing an entire type or an entire declaration
|
||||
which only lacks the actual "data-type" specifier (at its left end),
|
||||
@ -112,13 +121,16 @@ concat3 (s1, s2, s3)
|
||||
that look as expected. */
|
||||
|
||||
static char *
|
||||
affix_data_type (type_or_decl)
|
||||
char *type_or_decl;
|
||||
affix_data_type (param)
|
||||
const char *param;
|
||||
{
|
||||
char *type_or_decl = (char *) alloca (strlen (param) + 1);
|
||||
char *p = type_or_decl;
|
||||
char *qualifiers_then_data_type;
|
||||
char saved;
|
||||
|
||||
strcpy (type_or_decl, param);
|
||||
|
||||
/* Skip as many leading const's or volatile's as there are. */
|
||||
|
||||
for (;;)
|
||||
@ -140,13 +152,13 @@ affix_data_type (type_or_decl)
|
||||
add a blank after the data-type of course. */
|
||||
|
||||
if (p == type_or_decl)
|
||||
return concat3 (data_type, " ", type_or_decl);
|
||||
return concat (data_type, " ", type_or_decl, NULL_PTR);
|
||||
|
||||
saved = *p;
|
||||
*p = '\0';
|
||||
qualifiers_then_data_type = concat (type_or_decl, data_type);
|
||||
qualifiers_then_data_type = concat (type_or_decl, data_type, NULL_PTR);
|
||||
*p = saved;
|
||||
return concat3 (qualifiers_then_data_type, " ", p);
|
||||
return concat (qualifiers_then_data_type, " ", p, NULL_PTR);
|
||||
}
|
||||
|
||||
/* Given a tree node which represents some "function type", generate the
|
||||
@ -156,12 +168,12 @@ affix_data_type (type_or_decl)
|
||||
we are currently aiming for is non-ansi, then we just return a pair
|
||||
of empty parens here. */
|
||||
|
||||
static char *
|
||||
static const char *
|
||||
gen_formal_list_for_type (fntype, style)
|
||||
tree fntype;
|
||||
formals_style style;
|
||||
{
|
||||
char *formal_list = "";
|
||||
const char *formal_list = "";
|
||||
tree formal_type;
|
||||
|
||||
if (style != ansi)
|
||||
@ -170,16 +182,16 @@ gen_formal_list_for_type (fntype, style)
|
||||
formal_type = TYPE_ARG_TYPES (fntype);
|
||||
while (formal_type && TREE_VALUE (formal_type) != void_type_node)
|
||||
{
|
||||
char *this_type;
|
||||
const char *this_type;
|
||||
|
||||
if (*formal_list)
|
||||
formal_list = concat (formal_list, ", ");
|
||||
formal_list = concat (formal_list, ", ", NULL_PTR);
|
||||
|
||||
this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
|
||||
formal_list
|
||||
= ((strlen (this_type))
|
||||
? concat (formal_list, affix_data_type (this_type))
|
||||
: concat (formal_list, data_type));
|
||||
? concat (formal_list, affix_data_type (this_type), NULL_PTR)
|
||||
: concat (formal_list, data_type, NULL_PTR));
|
||||
|
||||
formal_type = TREE_CHAIN (formal_type);
|
||||
}
|
||||
@ -228,10 +240,10 @@ gen_formal_list_for_type (fntype, style)
|
||||
petered out to a NULL (i.e. without being terminated by a
|
||||
void_type_node) then we need to tack on an ellipsis. */
|
||||
if (!formal_type)
|
||||
formal_list = concat (formal_list, ", ...");
|
||||
formal_list = concat (formal_list, ", ...", NULL_PTR);
|
||||
}
|
||||
|
||||
return concat3 (" (", formal_list, ")");
|
||||
return concat (" (", formal_list, ")", NULL_PTR);
|
||||
}
|
||||
|
||||
/* For the generation of an ANSI prototype for a function definition, we have
|
||||
@ -276,37 +288,37 @@ deserves_ellipsis (fntype)
|
||||
This routine returns a string which is the source form for the entire
|
||||
function formal parameter list. */
|
||||
|
||||
static char *
|
||||
static const char *
|
||||
gen_formal_list_for_func_def (fndecl, style)
|
||||
tree fndecl;
|
||||
formals_style style;
|
||||
{
|
||||
char *formal_list = "";
|
||||
const char *formal_list = "";
|
||||
tree formal_decl;
|
||||
|
||||
formal_decl = DECL_ARGUMENTS (fndecl);
|
||||
while (formal_decl)
|
||||
{
|
||||
char *this_formal;
|
||||
const char *this_formal;
|
||||
|
||||
if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
|
||||
formal_list = concat (formal_list, ", ");
|
||||
formal_list = concat (formal_list, ", ", NULL_PTR);
|
||||
this_formal = gen_decl (formal_decl, 0, style);
|
||||
if (style == k_and_r_decls)
|
||||
formal_list = concat3 (formal_list, this_formal, "; ");
|
||||
formal_list = concat (formal_list, this_formal, "; ", NULL_PTR);
|
||||
else
|
||||
formal_list = concat (formal_list, this_formal);
|
||||
formal_list = concat (formal_list, this_formal, NULL_PTR);
|
||||
formal_decl = TREE_CHAIN (formal_decl);
|
||||
}
|
||||
if (style == ansi)
|
||||
{
|
||||
if (!DECL_ARGUMENTS (fndecl))
|
||||
formal_list = concat (formal_list, "void");
|
||||
formal_list = concat (formal_list, "void", NULL_PTR);
|
||||
if (deserves_ellipsis (TREE_TYPE (fndecl)))
|
||||
formal_list = concat (formal_list, ", ...");
|
||||
formal_list = concat (formal_list, ", ...", NULL_PTR);
|
||||
}
|
||||
if ((style == ansi) || (style == k_and_r_names))
|
||||
formal_list = concat3 (" (", formal_list, ")");
|
||||
formal_list = concat (" (", formal_list, ")", NULL_PTR);
|
||||
return formal_list;
|
||||
}
|
||||
|
||||
@ -351,9 +363,9 @@ gen_formal_list_for_func_def (fndecl, style)
|
||||
to do at this point is for the initial caller to prepend the "data_type"
|
||||
string onto the returned "seed". */
|
||||
|
||||
static char *
|
||||
static const char *
|
||||
gen_type (ret_val, t, style)
|
||||
char *ret_val;
|
||||
const char *ret_val;
|
||||
tree t;
|
||||
formals_style style;
|
||||
{
|
||||
@ -368,14 +380,14 @@ gen_type (ret_val, t, style)
|
||||
{
|
||||
case POINTER_TYPE:
|
||||
if (TYPE_READONLY (t))
|
||||
ret_val = concat ("const ", ret_val);
|
||||
ret_val = concat ("const ", ret_val, NULL_PTR);
|
||||
if (TYPE_VOLATILE (t))
|
||||
ret_val = concat ("volatile ", ret_val);
|
||||
ret_val = concat ("volatile ", ret_val, NULL_PTR);
|
||||
|
||||
ret_val = concat ("*", ret_val);
|
||||
ret_val = concat ("*", ret_val, NULL_PTR);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
|
||||
ret_val = concat3 ("(", ret_val, ")");
|
||||
ret_val = concat ("(", ret_val, ")", NULL_PTR);
|
||||
|
||||
ret_val = gen_type (ret_val, TREE_TYPE (t), style);
|
||||
|
||||
@ -383,21 +395,26 @@ gen_type (ret_val, t, style)
|
||||
|
||||
case ARRAY_TYPE:
|
||||
if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
|
||||
ret_val = gen_type (concat (ret_val, "[]"), TREE_TYPE (t), style);
|
||||
ret_val = gen_type (concat (ret_val, "[]", NULL_PTR),
|
||||
TREE_TYPE (t), style);
|
||||
else if (int_size_in_bytes (t) == 0)
|
||||
ret_val = gen_type (concat (ret_val, "[0]"), TREE_TYPE (t), style);
|
||||
ret_val = gen_type (concat (ret_val, "[0]", NULL_PTR),
|
||||
TREE_TYPE (t), style);
|
||||
else
|
||||
{
|
||||
int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t)));
|
||||
char buff[10];
|
||||
sprintf (buff, "[%d]", size);
|
||||
ret_val = gen_type (concat (ret_val, buff),
|
||||
ret_val = gen_type (concat (ret_val, buff, NULL_PTR),
|
||||
TREE_TYPE (t), style);
|
||||
}
|
||||
break;
|
||||
|
||||
case FUNCTION_TYPE:
|
||||
ret_val = gen_type (concat (ret_val, gen_formal_list_for_type (t, style)), TREE_TYPE (t), style);
|
||||
ret_val = gen_type (concat (ret_val,
|
||||
gen_formal_list_for_type (t, style),
|
||||
NULL_PTR),
|
||||
TREE_TYPE (t), style);
|
||||
break;
|
||||
|
||||
case IDENTIFIER_NODE:
|
||||
@ -424,13 +441,14 @@ gen_type (ret_val, t, style)
|
||||
chain_p = TYPE_FIELDS (t);
|
||||
while (chain_p)
|
||||
{
|
||||
data_type = concat (data_type, gen_decl (chain_p, 0, ansi));
|
||||
data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
|
||||
NULL_PTR);
|
||||
chain_p = TREE_CHAIN (chain_p);
|
||||
data_type = concat (data_type, "; ");
|
||||
data_type = concat (data_type, "; ", NULL_PTR);
|
||||
}
|
||||
data_type = concat3 ("{ ", data_type, "}");
|
||||
data_type = concat ("{ ", data_type, "}", NULL_PTR);
|
||||
}
|
||||
data_type = concat ("struct ", data_type);
|
||||
data_type = concat ("struct ", data_type, NULL_PTR);
|
||||
break;
|
||||
|
||||
case UNION_TYPE:
|
||||
@ -442,13 +460,14 @@ gen_type (ret_val, t, style)
|
||||
chain_p = TYPE_FIELDS (t);
|
||||
while (chain_p)
|
||||
{
|
||||
data_type = concat (data_type, gen_decl (chain_p, 0, ansi));
|
||||
data_type = concat (data_type, gen_decl (chain_p, 0, ansi),
|
||||
NULL_PTR);
|
||||
chain_p = TREE_CHAIN (chain_p);
|
||||
data_type = concat (data_type, "; ");
|
||||
data_type = concat (data_type, "; ", NULL_PTR);
|
||||
}
|
||||
data_type = concat3 ("{ ", data_type, "}");
|
||||
data_type = concat ("{ ", data_type, "}", NULL_PTR);
|
||||
}
|
||||
data_type = concat ("union ", data_type);
|
||||
data_type = concat ("union ", data_type, NULL_PTR);
|
||||
break;
|
||||
|
||||
case ENUMERAL_TYPE:
|
||||
@ -461,14 +480,14 @@ gen_type (ret_val, t, style)
|
||||
while (chain_p)
|
||||
{
|
||||
data_type = concat (data_type,
|
||||
IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)));
|
||||
IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL_PTR);
|
||||
chain_p = TREE_CHAIN (chain_p);
|
||||
if (chain_p)
|
||||
data_type = concat (data_type, ", ");
|
||||
data_type = concat (data_type, ", ", NULL_PTR);
|
||||
}
|
||||
data_type = concat3 ("{ ", data_type, " }");
|
||||
data_type = concat ("{ ", data_type, " }", NULL_PTR);
|
||||
}
|
||||
data_type = concat ("enum ", data_type);
|
||||
data_type = concat ("enum ", data_type, NULL_PTR);
|
||||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
@ -478,9 +497,9 @@ gen_type (ret_val, t, style)
|
||||
case INTEGER_TYPE:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
|
||||
/* Normally, `unsigned' is part of the deal. Not so if it comes
|
||||
with `const' or `volatile'. */
|
||||
if (TREE_UNSIGNED (t) && (TYPE_READONLY (t) || TYPE_VOLATILE (t)))
|
||||
data_type = concat ("unsigned ", data_type);
|
||||
with a type qualifier. */
|
||||
if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
|
||||
data_type = concat ("unsigned ", data_type, NULL_PTR);
|
||||
break;
|
||||
|
||||
case REAL_TYPE:
|
||||
@ -500,9 +519,11 @@ gen_type (ret_val, t, style)
|
||||
}
|
||||
}
|
||||
if (TYPE_READONLY (t))
|
||||
ret_val = concat ("const ", ret_val);
|
||||
ret_val = concat ("const ", ret_val, NULL_PTR);
|
||||
if (TYPE_VOLATILE (t))
|
||||
ret_val = concat ("volatile ", ret_val);
|
||||
ret_val = concat ("volatile ", ret_val, NULL_PTR);
|
||||
if (TYPE_RESTRICT (t))
|
||||
ret_val = concat ("restrict ", ret_val, NULL_PTR);
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
@ -516,13 +537,13 @@ gen_type (ret_val, t, style)
|
||||
associated with a function definition. In this case, we can assume that
|
||||
an attached list of DECL nodes for function formal arguments is present. */
|
||||
|
||||
static char *
|
||||
static const char *
|
||||
gen_decl (decl, is_func_definition, style)
|
||||
tree decl;
|
||||
int is_func_definition;
|
||||
formals_style style;
|
||||
{
|
||||
char *ret_val;
|
||||
const char *ret_val;
|
||||
|
||||
if (DECL_NAME (decl))
|
||||
ret_val = IDENTIFIER_POINTER (DECL_NAME (decl));
|
||||
@ -544,9 +565,9 @@ gen_decl (decl, is_func_definition, style)
|
||||
generate the qualifiers here. */
|
||||
|
||||
if (TREE_THIS_VOLATILE (decl))
|
||||
ret_val = concat ("volatile ", ret_val);
|
||||
ret_val = concat ("volatile ", ret_val, NULL_PTR);
|
||||
if (TREE_READONLY (decl))
|
||||
ret_val = concat ("const ", ret_val);
|
||||
ret_val = concat ("const ", ret_val, NULL_PTR);
|
||||
|
||||
data_type = "";
|
||||
|
||||
@ -564,7 +585,8 @@ gen_decl (decl, is_func_definition, style)
|
||||
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition)
|
||||
{
|
||||
ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi));
|
||||
ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi),
|
||||
NULL_PTR);
|
||||
|
||||
/* Since we have already added in the formals list stuff, here we don't
|
||||
add the whole "type" of the function we are considering (which
|
||||
@ -581,11 +603,11 @@ gen_decl (decl, is_func_definition, style)
|
||||
ret_val = affix_data_type (ret_val);
|
||||
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
|
||||
ret_val = concat ("register ", ret_val);
|
||||
ret_val = concat ("register ", ret_val, NULL_PTR);
|
||||
if (TREE_PUBLIC (decl))
|
||||
ret_val = concat ("extern ", ret_val);
|
||||
ret_val = concat ("extern ", ret_val, NULL_PTR);
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl))
|
||||
ret_val = concat ("static ", ret_val);
|
||||
ret_val = concat ("static ", ret_val, NULL_PTR);
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Subroutines shared by all languages that are variants of C.
|
||||
Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -27,6 +27,8 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "obstack.h"
|
||||
#include "toplev.h"
|
||||
#include "output.h"
|
||||
#include "c-pragma.h"
|
||||
#include "rtl.h"
|
||||
|
||||
#if USE_CPPLIB
|
||||
#include "cpplib.h"
|
||||
@ -50,19 +52,22 @@ extern struct obstack permanent_obstack;
|
||||
int skip_evaluation;
|
||||
|
||||
enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
|
||||
A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
|
||||
A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
|
||||
A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS};
|
||||
|
||||
enum format_type { printf_format_type, scanf_format_type,
|
||||
strftime_format_type };
|
||||
|
||||
static void declare_hidden_char_array PROTO((char *, char *));
|
||||
static void add_attribute PROTO((enum attrs, char *,
|
||||
static void declare_hidden_char_array PROTO((const char *, const char *));
|
||||
static void add_attribute PROTO((enum attrs, const char *,
|
||||
int, int, int));
|
||||
static void init_attributes PROTO((void));
|
||||
static void record_function_format PROTO((tree, tree, enum format_type,
|
||||
int, int));
|
||||
static void record_international_format PROTO((tree, tree, int));
|
||||
static tree c_find_base_decl PROTO((tree));
|
||||
static int default_valid_lang_attribute PROTO ((tree, tree, tree, tree));
|
||||
|
||||
/* Keep a stack of if statements. We record the number of compound
|
||||
statements seen up to the if keyword, as well as the line number
|
||||
@ -73,9 +78,10 @@ typedef struct
|
||||
{
|
||||
int compstmt_count;
|
||||
int line;
|
||||
char *file;
|
||||
const char *file;
|
||||
int needs_warning;
|
||||
} if_elt;
|
||||
static void tfaff PROTO((void));
|
||||
|
||||
static if_elt *if_stack;
|
||||
|
||||
@ -153,12 +159,12 @@ c_expand_start_else ()
|
||||
expand_start_else ();
|
||||
}
|
||||
|
||||
/* Make bindings for __FUNCTION__ and __PRETTY_FUNCTION__. */
|
||||
/* Make bindings for __FUNCTION__, __PRETTY_FUNCTION__, and __func__. */
|
||||
|
||||
void
|
||||
declare_function_name ()
|
||||
{
|
||||
char *name, *printable_name;
|
||||
const char *name, *printable_name;
|
||||
|
||||
if (current_function_decl == NULL)
|
||||
{
|
||||
@ -177,11 +183,14 @@ declare_function_name ()
|
||||
|
||||
declare_hidden_char_array ("__FUNCTION__", name);
|
||||
declare_hidden_char_array ("__PRETTY_FUNCTION__", printable_name);
|
||||
/* The ISO C people "of course" couldn't use __FUNCTION__ in the
|
||||
ISO C 9x standard; instead a new variable is invented. */
|
||||
declare_hidden_char_array ("__func__", name);
|
||||
}
|
||||
|
||||
static void
|
||||
declare_hidden_char_array (name, value)
|
||||
char *name, *value;
|
||||
const char *name, *value;
|
||||
{
|
||||
tree decl, type, init;
|
||||
int vlen;
|
||||
@ -262,7 +271,7 @@ combine_strings (strings)
|
||||
? wchar_bytes : 1));
|
||||
if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
|
||||
{
|
||||
bcopy (TREE_STRING_POINTER (t), q, len);
|
||||
memcpy (q, TREE_STRING_POINTER (t), len);
|
||||
q += len;
|
||||
}
|
||||
else
|
||||
@ -290,7 +299,6 @@ combine_strings (strings)
|
||||
value = make_node (STRING_CST);
|
||||
TREE_STRING_POINTER (value) = p;
|
||||
TREE_STRING_LENGTH (value) = length;
|
||||
TREE_CONSTANT (value) = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -305,8 +313,9 @@ combine_strings (strings)
|
||||
|
||||
/* Create the array type for the string constant.
|
||||
-Wwrite-strings says make the string constant an array of const char
|
||||
so that copying it to a non-const pointer will get a warning. */
|
||||
if (warn_write_strings
|
||||
so that copying it to a non-const pointer will get a warning.
|
||||
For C++, this is the standard behavior. */
|
||||
if (flag_const_strings
|
||||
&& (! flag_traditional && ! flag_writable_strings))
|
||||
{
|
||||
tree elements
|
||||
@ -320,7 +329,8 @@ combine_strings (strings)
|
||||
TREE_TYPE (value)
|
||||
= build_array_type (wide_flag ? wchar_type_node : char_type_node,
|
||||
build_index_type (build_int_2 (nchars - 1, 0)));
|
||||
TREE_CONSTANT (value) = 1;
|
||||
|
||||
TREE_READONLY (value) = TREE_CONSTANT (value) = ! flag_writable_strings;
|
||||
TREE_STATIC (value) = 1;
|
||||
return value;
|
||||
}
|
||||
@ -339,7 +349,7 @@ static int attrtab_idx = 0;
|
||||
static void
|
||||
add_attribute (id, string, min_len, max_len, decl_req)
|
||||
enum attrs id;
|
||||
char *string;
|
||||
const char *string;
|
||||
int min_len, max_len;
|
||||
int decl_req;
|
||||
{
|
||||
@ -382,8 +392,29 @@ init_attributes ()
|
||||
add_attribute (A_FORMAT_ARG, "format_arg", 1, 1, 1);
|
||||
add_attribute (A_WEAK, "weak", 0, 0, 1);
|
||||
add_attribute (A_ALIAS, "alias", 1, 1, 1);
|
||||
add_attribute (A_NO_INSTRUMENT_FUNCTION, "no_instrument_function", 0, 0, 1);
|
||||
add_attribute (A_NO_CHECK_MEMORY_USAGE, "no_check_memory_usage", 0, 0, 1);
|
||||
}
|
||||
|
||||
/* Default implementation of valid_lang_attribute, below. By default, there
|
||||
are no language-specific attributes. */
|
||||
|
||||
static int
|
||||
default_valid_lang_attribute (attr_name, attr_args, decl, type)
|
||||
tree attr_name ATTRIBUTE_UNUSED;
|
||||
tree attr_args ATTRIBUTE_UNUSED;
|
||||
tree decl ATTRIBUTE_UNUSED;
|
||||
tree type ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid language-specific
|
||||
attribute for either declaration DECL or type TYPE and 0 otherwise. */
|
||||
|
||||
int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree))
|
||||
= default_valid_lang_attribute;
|
||||
|
||||
/* Process the attributes listed in ATTRIBUTES and PREFIX_ATTRIBUTES
|
||||
and install them in NODE, which is either a DECL (including a TYPE_DECL)
|
||||
or a TYPE. PREFIX_ATTRIBUTES can appear after the declaration specifiers
|
||||
@ -409,6 +440,18 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
else if (TREE_CODE_CLASS (TREE_CODE (node)) == 't')
|
||||
type = node, is_type = 1;
|
||||
|
||||
#ifdef PRAGMA_INSERT_ATTRIBUTES
|
||||
/* If the code in c-pragma.c wants to insert some attributes then
|
||||
allow it to do so. Do this before allowing machine back ends to
|
||||
insert attributes, so that they have the opportunity to override
|
||||
anything done here. */
|
||||
PRAGMA_INSERT_ATTRIBUTES (node, & attributes, & prefix_attributes);
|
||||
#endif
|
||||
|
||||
#ifdef INSERT_ATTRIBUTES
|
||||
INSERT_ATTRIBUTES (node, & attributes, & prefix_attributes);
|
||||
#endif
|
||||
|
||||
attributes = chainon (prefix_attributes, attributes);
|
||||
|
||||
for (a = attributes; a; a = TREE_CHAIN (a))
|
||||
@ -424,7 +467,8 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
|
||||
if (i == attrtab_idx)
|
||||
{
|
||||
if (! valid_machine_attribute (name, args, decl, type))
|
||||
if (! valid_machine_attribute (name, args, decl, type)
|
||||
&& ! (* valid_lang_attribute) (name, args, decl, type))
|
||||
warning ("`%s' attribute directive ignored",
|
||||
IDENTIFIER_POINTER (name));
|
||||
else if (decl != 0)
|
||||
@ -491,7 +535,8 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
TREE_USED (type) = 1;
|
||||
else if (TREE_CODE (decl) == PARM_DECL
|
||||
|| TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == FUNCTION_DECL)
|
||||
|| TREE_CODE (decl) == FUNCTION_DECL
|
||||
|| TREE_CODE (decl) == LABEL_DECL)
|
||||
TREE_USED (decl) = 1;
|
||||
else
|
||||
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
||||
@ -555,7 +600,7 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
else
|
||||
{
|
||||
int j;
|
||||
char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
|
||||
const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
|
||||
int len = strlen (p);
|
||||
enum machine_mode mode = VOIDmode;
|
||||
tree typefm;
|
||||
@ -633,7 +678,7 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
= (args ? TREE_VALUE (args)
|
||||
: size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
|
||||
int align;
|
||||
|
||||
|
||||
/* Strip any NOPs of any kind. */
|
||||
while (TREE_CODE (align_expr) == NOP_EXPR
|
||||
|| TREE_CODE (align_expr) == CONVERT_EXPR
|
||||
@ -687,7 +732,7 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
}
|
||||
else
|
||||
{
|
||||
char *p = IDENTIFIER_POINTER (format_type_id);
|
||||
const char *p = IDENTIFIER_POINTER (format_type_id);
|
||||
|
||||
if (!strcmp (p, "printf") || !strcmp (p, "__printf__"))
|
||||
format_type = printf_format_type;
|
||||
@ -698,7 +743,7 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
format_type = strftime_format_type;
|
||||
else
|
||||
{
|
||||
error ("`%s' is an unrecognized format function type", p);
|
||||
warning ("`%s' is an unrecognized format function type", p);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -864,6 +909,40 @@ decl_attributes (node, attributes, prefix_attributes)
|
||||
else
|
||||
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
|
||||
break;
|
||||
|
||||
case A_NO_CHECK_MEMORY_USAGE:
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL)
|
||||
{
|
||||
error_with_decl (decl,
|
||||
"`%s' attribute applies only to functions",
|
||||
IDENTIFIER_POINTER (name));
|
||||
}
|
||||
else if (DECL_INITIAL (decl))
|
||||
{
|
||||
error_with_decl (decl,
|
||||
"can't set `%s' attribute after definition",
|
||||
IDENTIFIER_POINTER (name));
|
||||
}
|
||||
else
|
||||
DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
|
||||
break;
|
||||
|
||||
case A_NO_INSTRUMENT_FUNCTION:
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL)
|
||||
{
|
||||
error_with_decl (decl,
|
||||
"`%s' attribute applies only to functions",
|
||||
IDENTIFIER_POINTER (name));
|
||||
}
|
||||
else if (DECL_INITIAL (decl))
|
||||
{
|
||||
error_with_decl (decl,
|
||||
"can't set `%s' attribute after definition",
|
||||
IDENTIFIER_POINTER (name));
|
||||
}
|
||||
else
|
||||
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -983,7 +1062,7 @@ strip_attrs (specs_attrs)
|
||||
#define T_ST &sizetype
|
||||
|
||||
typedef struct {
|
||||
char *format_chars;
|
||||
const char *format_chars;
|
||||
int pointer_count;
|
||||
/* Type of argument if no length modifier is used. */
|
||||
tree *nolen;
|
||||
@ -1006,7 +1085,7 @@ typedef struct {
|
||||
If NULL, then this modifier is not allowed. */
|
||||
tree *zlen;
|
||||
/* List of other modifier characters allowed with these options. */
|
||||
char *flag_chars;
|
||||
const char *flag_chars;
|
||||
} format_char_info;
|
||||
|
||||
static format_char_info print_char_table[] = {
|
||||
@ -1022,7 +1101,7 @@ static format_char_info print_char_table[] = {
|
||||
{ "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "-wp" },
|
||||
{ "p", 1, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "-w" },
|
||||
{ "n", 1, T_I, NULL, T_S, T_L, T_LL, NULL, NULL, "" },
|
||||
{ NULL }
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static format_char_info scan_char_table[] = {
|
||||
@ -1036,7 +1115,7 @@ static format_char_info scan_char_table[] = {
|
||||
{ "S", 1, T_W, NULL, NULL, NULL, NULL, NULL, NULL, "*a" },
|
||||
{ "p", 2, T_V, NULL, NULL, NULL, NULL, NULL, NULL, "*" },
|
||||
{ "n", 1, T_I, T_C, T_S, T_L, T_LL, NULL, NULL, "" },
|
||||
{ NULL }
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* Handle format characters recognized by glibc's strftime.c.
|
||||
@ -1061,7 +1140,7 @@ static format_char_info time_char_table[] = {
|
||||
{ "p", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "#" },
|
||||
{ "bh", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "^" },
|
||||
{ "CY", 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "-_0EOw" },
|
||||
{ NULL }
|
||||
{ NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
typedef struct function_format_info
|
||||
@ -1206,7 +1285,11 @@ record_international_format (name, assembler_name, format_num)
|
||||
info->format_num = format_num;
|
||||
}
|
||||
|
||||
static char tfaff[] = "too few arguments for format";
|
||||
static void
|
||||
tfaff ()
|
||||
{
|
||||
warning ("too few arguments for format");
|
||||
}
|
||||
|
||||
/* Check the argument list of a call to printf, scanf, etc.
|
||||
NAME is the function identifier.
|
||||
@ -1256,7 +1339,7 @@ check_format_info (info, params)
|
||||
tree cur_type;
|
||||
tree wanted_type;
|
||||
tree first_fillin_param;
|
||||
char *format_chars;
|
||||
const char *format_chars;
|
||||
format_char_info *fci = NULL;
|
||||
char flag_chars[8];
|
||||
int has_operand_number = 0;
|
||||
@ -1420,7 +1503,7 @@ check_format_info (info, params)
|
||||
it is an operand number, so set PARAMS to that operand. */
|
||||
if (*format_chars >= '0' && *format_chars <= '9')
|
||||
{
|
||||
char *p = format_chars;
|
||||
const char *p = format_chars;
|
||||
|
||||
while (*p >= '0' && *p++ <= '9')
|
||||
;
|
||||
@ -1473,7 +1556,7 @@ check_format_info (info, params)
|
||||
++format_chars;
|
||||
if (params == 0)
|
||||
{
|
||||
warning (tfaff);
|
||||
tfaff ();
|
||||
return;
|
||||
}
|
||||
if (info->first_arg_num != 0)
|
||||
@ -1516,7 +1599,7 @@ check_format_info (info, params)
|
||||
++format_chars;
|
||||
if (params == 0)
|
||||
{
|
||||
warning (tfaff);
|
||||
tfaff ();
|
||||
return;
|
||||
}
|
||||
cur_param = TREE_VALUE (params);
|
||||
@ -1686,7 +1769,7 @@ check_format_info (info, params)
|
||||
if (precise && index (flag_chars, '0') != 0
|
||||
&& (format_char == 'd' || format_char == 'i'
|
||||
|| format_char == 'o' || format_char == 'u'
|
||||
|| format_char == 'x' || format_char == 'x'))
|
||||
|| format_char == 'x' || format_char == 'X'))
|
||||
warning ("`0' flag ignored with precision specifier and `%c' format",
|
||||
format_char);
|
||||
switch (length_char)
|
||||
@ -1711,7 +1794,7 @@ check_format_info (info, params)
|
||||
continue;
|
||||
if (params == 0)
|
||||
{
|
||||
warning (tfaff);
|
||||
tfaff ();
|
||||
return;
|
||||
}
|
||||
cur_param = TREE_VALUE (params);
|
||||
@ -1737,9 +1820,9 @@ check_format_info (info, params)
|
||||
continue;
|
||||
}
|
||||
if (TREE_CODE (cur_type) != ERROR_MARK)
|
||||
warning ("format argument is not a %s (arg %d)",
|
||||
((fci->pointer_count + aflag == 1)
|
||||
? "pointer" : "pointer to a pointer"),
|
||||
warning ((fci->pointer_count + aflag == 1
|
||||
? "format argument is not a pointer (arg %d)"
|
||||
: "format argument is not a pointer to a pointer (arg %d)"),
|
||||
arg_num);
|
||||
break;
|
||||
}
|
||||
@ -1779,8 +1862,8 @@ check_format_info (info, params)
|
||||
&& (TYPE_MAIN_VARIANT (cur_type) == signed_char_type_node
|
||||
|| TYPE_MAIN_VARIANT (cur_type) == unsigned_char_type_node)))
|
||||
{
|
||||
register char *this;
|
||||
register char *that;
|
||||
register const char *this;
|
||||
register const char *that;
|
||||
|
||||
this = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (wanted_type)));
|
||||
that = 0;
|
||||
@ -2049,8 +2132,10 @@ type_for_mode (mode, unsignedp)
|
||||
if (mode == TYPE_MODE (intDI_type_node))
|
||||
return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
|
||||
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
if (mode == TYPE_MODE (intTI_type_node))
|
||||
return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
|
||||
#endif
|
||||
|
||||
if (mode == TYPE_MODE (float_type_node))
|
||||
return float_type_node;
|
||||
@ -2108,7 +2193,7 @@ void
|
||||
binary_op_error (code)
|
||||
enum tree_code code;
|
||||
{
|
||||
register char *opname;
|
||||
register const char *opname;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
@ -2399,18 +2484,18 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
|
||||
/* This is the case of (char)x >?< 0x80, which people used to use
|
||||
expecting old C compilers to change the 0x80 into -0x80. */
|
||||
if (val == boolean_false_node)
|
||||
warning ("comparison is always 0 due to limited range of data type");
|
||||
warning ("comparison is always false due to limited range of data type");
|
||||
if (val == boolean_true_node)
|
||||
warning ("comparison is always 1 due to limited range of data type");
|
||||
warning ("comparison is always true due to limited range of data type");
|
||||
}
|
||||
|
||||
if (!min_lt && unsignedp0 && TREE_CODE (primop0) != INTEGER_CST)
|
||||
{
|
||||
/* This is the case of (unsigned char)x >?< -1 or < 0. */
|
||||
if (val == boolean_false_node)
|
||||
warning ("comparison is always 0 due to limited range of data type");
|
||||
warning ("comparison is always false due to limited range of data type");
|
||||
if (val == boolean_true_node)
|
||||
warning ("comparison is always 1 due to limited range of data type");
|
||||
warning ("comparison is always true due to limited range of data type");
|
||||
}
|
||||
|
||||
if (val != 0)
|
||||
@ -2476,7 +2561,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
|
||||
&& ! (TREE_CODE (primop0) == INTEGER_CST
|
||||
&& ! TREE_OVERFLOW (convert (signed_type (type),
|
||||
primop0))))
|
||||
warning ("unsigned value >= 0 is always 1");
|
||||
warning ("comparison of unsigned expression >= 0 is always true");
|
||||
value = boolean_true_node;
|
||||
break;
|
||||
|
||||
@ -2485,7 +2570,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
|
||||
&& ! (TREE_CODE (primop0) == INTEGER_CST
|
||||
&& ! TREE_OVERFLOW (convert (signed_type (type),
|
||||
primop0))))
|
||||
warning ("unsigned value < 0 is always 0");
|
||||
warning ("comparison of unsigned expression < 0 is always false");
|
||||
value = boolean_false_node;
|
||||
break;
|
||||
|
||||
@ -2710,7 +2795,7 @@ truthvalue_conversion (expr)
|
||||
unsigned char *yy_cur, *yy_lim;
|
||||
|
||||
#define GETC() (yy_cur < yy_lim ? *yy_cur++ : yy_get_token ())
|
||||
#define UNGETC(c) ((c), yy_cur--)
|
||||
#define UNGETC(c) ((c) == EOF ? 0 : yy_cur--)
|
||||
|
||||
int
|
||||
yy_get_token ()
|
||||
@ -2884,15 +2969,134 @@ get_directive_line (finput)
|
||||
down to the element type of an array. */
|
||||
|
||||
tree
|
||||
c_build_type_variant (type, constp, volatilep)
|
||||
c_build_qualified_type (type, type_quals)
|
||||
tree type;
|
||||
int constp, volatilep;
|
||||
int type_quals;
|
||||
{
|
||||
/* A restrict-qualified pointer type must be a pointer to object or
|
||||
incomplete type. Note that the use of POINTER_TYPE_P also allows
|
||||
REFERENCE_TYPEs, which is appropriate for C++. Unfortunately,
|
||||
the C++ front-end also use POINTER_TYPE for pointer-to-member
|
||||
values, so even though it should be illegal to use `restrict'
|
||||
with such an entity we don't flag that here. Thus, special case
|
||||
code for that case is required in the C++ front-end. */
|
||||
if ((type_quals & TYPE_QUAL_RESTRICT)
|
||||
&& (!POINTER_TYPE_P (type)
|
||||
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type))))
|
||||
{
|
||||
error ("invalid use of `restrict'");
|
||||
type_quals &= ~TYPE_QUAL_RESTRICT;
|
||||
}
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return build_array_type (c_build_type_variant (TREE_TYPE (type),
|
||||
constp, volatilep),
|
||||
return build_array_type (c_build_qualified_type (TREE_TYPE (type),
|
||||
type_quals),
|
||||
TYPE_DOMAIN (type));
|
||||
return build_type_variant (type, constp, volatilep);
|
||||
return build_qualified_type (type, type_quals);
|
||||
}
|
||||
|
||||
/* Apply the TYPE_QUALS to the new DECL. */
|
||||
|
||||
void
|
||||
c_apply_type_quals_to_decl (type_quals, decl)
|
||||
int type_quals;
|
||||
tree decl;
|
||||
{
|
||||
if (type_quals & TYPE_QUAL_CONST)
|
||||
TREE_READONLY (decl) = 1;
|
||||
if (type_quals & TYPE_QUAL_VOLATILE)
|
||||
{
|
||||
TREE_SIDE_EFFECTS (decl) = 1;
|
||||
TREE_THIS_VOLATILE (decl) = 1;
|
||||
}
|
||||
if (type_quals & TYPE_QUAL_RESTRICT)
|
||||
{
|
||||
if (!TREE_TYPE (decl)
|
||||
|| !POINTER_TYPE_P (TREE_TYPE (decl))
|
||||
|| !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
|
||||
error ("invalid use of `restrict'");
|
||||
else if (flag_strict_aliasing)
|
||||
{
|
||||
/* No two restricted pointers can point at the same thing.
|
||||
However, a restricted pointer can point at the same thing
|
||||
as an unrestricted pointer, if that unrestricted pointer
|
||||
is based on the restricted pointer. So, we make the
|
||||
alias set for the restricted pointer a subset of the
|
||||
alias set for the type pointed to by the type of the
|
||||
decl. */
|
||||
|
||||
int pointed_to_alias_set
|
||||
= get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
|
||||
|
||||
if (!pointed_to_alias_set)
|
||||
/* It's not legal to make a subset of alias set zero. */
|
||||
;
|
||||
else
|
||||
{
|
||||
DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
|
||||
record_alias_subset (pointed_to_alias_set,
|
||||
DECL_POINTER_ALIAS_SET (decl));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* T is an expression with pointer type. Find the DECL on which this
|
||||
expression is based. (For example, in `a[i]' this would be `a'.)
|
||||
If there is no such DECL, or a unique decl cannot be determined,
|
||||
NULL_TREE is retured. */
|
||||
|
||||
static tree
|
||||
c_find_base_decl (t)
|
||||
tree t;
|
||||
{
|
||||
int i;
|
||||
tree decl;
|
||||
|
||||
if (t == NULL_TREE || t == error_mark_node)
|
||||
return NULL_TREE;
|
||||
|
||||
if (!POINTER_TYPE_P (TREE_TYPE (t)))
|
||||
return NULL_TREE;
|
||||
|
||||
decl = NULL_TREE;
|
||||
|
||||
if (TREE_CODE (t) == FIELD_DECL
|
||||
|| TREE_CODE (t) == PARM_DECL
|
||||
|| TREE_CODE (t) == VAR_DECL)
|
||||
/* Aha, we found a pointer-typed declaration. */
|
||||
return t;
|
||||
|
||||
/* It would be nice to deal with COMPONENT_REFs here. If we could
|
||||
tell that `a' and `b' were the same, then `a->f' and `b->f' are
|
||||
also the same. */
|
||||
|
||||
/* Handle general expressions. */
|
||||
switch (TREE_CODE_CLASS (TREE_CODE (t)))
|
||||
{
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
for (i = tree_code_length [(int) TREE_CODE (t)]; --i >= 0;)
|
||||
{
|
||||
tree d = c_find_base_decl (TREE_OPERAND (t, i));
|
||||
if (d)
|
||||
{
|
||||
if (!decl)
|
||||
decl = d;
|
||||
else if (d && d != decl)
|
||||
/* Two different declarations. That's confusing; let's
|
||||
just assume we don't know what's going on. */
|
||||
decl = NULL_TREE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return decl;
|
||||
}
|
||||
|
||||
/* Return the typed-based alias set for T, which may be an expression
|
||||
@ -2902,21 +3106,20 @@ int
|
||||
c_get_alias_set (t)
|
||||
tree t;
|
||||
{
|
||||
static int next_set = 0;
|
||||
tree type;
|
||||
tree u;
|
||||
|
||||
if (t == error_mark_node)
|
||||
return 0;
|
||||
|
||||
type = (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
|
||||
? t : TREE_TYPE (t);
|
||||
? t : TREE_TYPE (t);
|
||||
|
||||
if (type == error_mark_node)
|
||||
return 0;
|
||||
|
||||
if (TYPE_ALIAS_SET_KNOWN_P (type))
|
||||
/* If we've already calculated the value, just return it. */
|
||||
return TYPE_ALIAS_SET (type);
|
||||
/* Deal with special cases first; for certain kinds of references
|
||||
we're interested in more than just the type. */
|
||||
|
||||
if (TREE_CODE (t) == BIT_FIELD_REF)
|
||||
/* Perhaps reads and writes to this piece of data alias fields
|
||||
@ -2924,22 +3127,48 @@ c_get_alias_set (t)
|
||||
let's just assume that bitfields can alias everything, which is
|
||||
the conservative assumption. */
|
||||
return 0;
|
||||
if (TREE_CODE (t) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE)
|
||||
/* Permit type-punning when accessing a union, provided the
|
||||
access is directly through the union. For example, this code does
|
||||
not permit taking the address of a union member and then
|
||||
storing through it. Even the type-punning allowed here is a
|
||||
GCC extension, albeit a common and useful one; the C standard
|
||||
says that such accesses have implementation-defined behavior. */
|
||||
return 0;
|
||||
else if (TYPE_MAIN_VARIANT (type) != type)
|
||||
|
||||
/* Permit type-punning when accessing a union, provided the access
|
||||
is directly through the union. For example, this code does not
|
||||
permit taking the address of a union member and then storing
|
||||
through it. Even the type-punning allowed here is a GCC
|
||||
extension, albeit a common and useful one; the C standard says
|
||||
that such accesses have implementation-defined behavior. */
|
||||
for (u = t;
|
||||
TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
|
||||
u = TREE_OPERAND (u, 0))
|
||||
if (TREE_CODE (u) == COMPONENT_REF
|
||||
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
|
||||
return 0;
|
||||
|
||||
if (TREE_CODE (t) == INDIRECT_REF)
|
||||
{
|
||||
/* The C standard specifically allows aliasing between
|
||||
cv-qualified variants of types. */
|
||||
TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
|
||||
return TYPE_ALIAS_SET (type);
|
||||
/* Check for accesses through restrict-qualified pointers. */
|
||||
tree decl = c_find_base_decl (TREE_OPERAND (t, 0));
|
||||
|
||||
if (decl && DECL_POINTER_ALIAS_SET_KNOWN_P (decl))
|
||||
/* We use the alias set indicated in the declaration. */
|
||||
return DECL_POINTER_ALIAS_SET (decl);
|
||||
}
|
||||
|
||||
/* From here on, only the type matters. */
|
||||
|
||||
if (TREE_CODE (t) == COMPONENT_REF
|
||||
&& DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)))
|
||||
/* Since build_modify_expr calls get_unwidened for stores to
|
||||
component references, the type of a bit field can be changed
|
||||
from (say) `unsigned int : 16' to `unsigned short' or from
|
||||
`enum E : 16' to `short'. We want the real type of the
|
||||
bit-field in this case, not some the integral equivalent. */
|
||||
type = DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1));
|
||||
|
||||
if (TYPE_ALIAS_SET_KNOWN_P (type))
|
||||
/* If we've already calculated the value, just return it. */
|
||||
return TYPE_ALIAS_SET (type);
|
||||
else if (TYPE_MAIN_VARIANT (type) != type)
|
||||
/* The C standard specifically allows aliasing between
|
||||
cv-qualified variants of types. */
|
||||
TYPE_ALIAS_SET (type) = c_get_alias_set (TYPE_MAIN_VARIANT (type));
|
||||
else if (TREE_CODE (type) == INTEGER_TYPE)
|
||||
{
|
||||
tree signed_variant;
|
||||
@ -2950,34 +3179,37 @@ c_get_alias_set (t)
|
||||
signed_variant = signed_type (type);
|
||||
|
||||
if (signed_variant != type)
|
||||
{
|
||||
TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
|
||||
return TYPE_ALIAS_SET (type);
|
||||
}
|
||||
TYPE_ALIAS_SET (type) = c_get_alias_set (signed_variant);
|
||||
else if (signed_variant == signed_char_type_node)
|
||||
/* The C standard guarantess that any object may be accessed
|
||||
via an lvalue that has character type. We don't have to
|
||||
check for unsigned_char_type_node or char_type_node because
|
||||
we are specifically looking at the signed variant. */
|
||||
{
|
||||
TYPE_ALIAS_SET (type) = 0;
|
||||
return TYPE_ALIAS_SET (type);
|
||||
}
|
||||
TYPE_ALIAS_SET (type) = 0;
|
||||
}
|
||||
else if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
/* Anything that can alias one of the array elements can alias
|
||||
the entire array as well. */
|
||||
TYPE_ALIAS_SET (type) = c_get_alias_set (TREE_TYPE (type));
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
/* There are no objects of FUNCTION_TYPE, so there's no point in
|
||||
using up an alias set for them. (There are, of course,
|
||||
pointers and references to functions, but that's
|
||||
different.) */
|
||||
TYPE_ALIAS_SET (type) = 0;
|
||||
else if (TREE_CODE (type) == RECORD_TYPE
|
||||
|| TREE_CODE (type) == UNION_TYPE)
|
||||
{
|
||||
/* If TYPE is a struct or union type then we're reading or
|
||||
writing an entire struct. Thus, we don't know anything about
|
||||
aliasing. (In theory, such an access can only alias objects
|
||||
whose type is the same as one of the fields, recursively, but
|
||||
we don't yet make any use of that information.) */
|
||||
TYPE_ALIAS_SET (type) = 0;
|
||||
return TYPE_ALIAS_SET (type);
|
||||
}
|
||||
/* If TYPE is a struct or union type then we're reading or
|
||||
writing an entire struct. Thus, we don't know anything about
|
||||
aliasing. (In theory, such an access can only alias objects
|
||||
whose type is the same as one of the fields, recursively, but
|
||||
we don't yet make any use of that information.) */
|
||||
TYPE_ALIAS_SET (type) = 0;
|
||||
|
||||
if (!TYPE_ALIAS_SET_KNOWN_P (type))
|
||||
/* TYPE is something we haven't seen before. Put it in a new
|
||||
alias set. */
|
||||
TYPE_ALIAS_SET (type) = new_alias_set ();
|
||||
|
||||
/* TYPE is something we haven't seen before. Put it in a new alias
|
||||
set. */
|
||||
TYPE_ALIAS_SET (type) = ++next_set;
|
||||
return TYPE_ALIAS_SET (type);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Language-level data type conversion for GNU C.
|
||||
Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 1988, 1991, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Process declarations and variables for C compiler.
|
||||
Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 92-98, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -37,9 +37,7 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#if USE_CPPLIB
|
||||
#include "cpplib.h"
|
||||
extern cpp_reader parse_in;
|
||||
extern cpp_options parse_options;
|
||||
static int cpp_initialized;
|
||||
extern cpp_reader parse_in;
|
||||
#endif
|
||||
|
||||
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
|
||||
@ -151,13 +149,17 @@ tree intQI_type_node;
|
||||
tree intHI_type_node;
|
||||
tree intSI_type_node;
|
||||
tree intDI_type_node;
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
tree intTI_type_node;
|
||||
#endif
|
||||
|
||||
tree unsigned_intQI_type_node;
|
||||
tree unsigned_intHI_type_node;
|
||||
tree unsigned_intSI_type_node;
|
||||
tree unsigned_intDI_type_node;
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
tree unsigned_intTI_type_node;
|
||||
#endif
|
||||
|
||||
/* a VOID_TYPE node. */
|
||||
|
||||
@ -424,7 +426,7 @@ tree static_ctors, static_dtors;
|
||||
static struct binding_level * make_binding_level PROTO((void));
|
||||
static void clear_limbo_values PROTO((tree));
|
||||
static int duplicate_decls PROTO((tree, tree, int));
|
||||
static char *redeclaration_error_message PROTO((tree, tree));
|
||||
static int redeclaration_error_message PROTO((tree, tree));
|
||||
static void storedecls PROTO((tree));
|
||||
static void storetags PROTO((tree));
|
||||
static tree lookup_tag PROTO((enum tree_code, tree,
|
||||
@ -464,6 +466,10 @@ int flag_no_nonansi_builtin;
|
||||
|
||||
int flag_traditional;
|
||||
|
||||
/* Nonzero means use the ISO C9x dialect of C. */
|
||||
|
||||
int flag_isoc9x = 0;
|
||||
|
||||
/* Nonzero means that we have builtin functions, and main is an int */
|
||||
|
||||
int flag_hosted = 1;
|
||||
@ -477,10 +483,6 @@ int flag_allow_single_precision = 0;
|
||||
int flag_signed_bitfields = 1;
|
||||
int explicit_flag_signed_bitfields = 0;
|
||||
|
||||
/* Nonzero means handle `#ident' directives. 0 means ignore them. */
|
||||
|
||||
int flag_no_ident = 0;
|
||||
|
||||
/* Nonzero means warn about use of implicit int. */
|
||||
|
||||
int warn_implicit_int;
|
||||
@ -498,7 +500,7 @@ int mesg_implicit_function_declaration;
|
||||
to get extra warnings from them. These warnings will be too numerous
|
||||
to be useful, except in thoroughly ANSIfied programs. */
|
||||
|
||||
int warn_write_strings;
|
||||
int flag_const_strings;
|
||||
|
||||
/* Nonzero means warn about pointer casts that can drop a type qualifier
|
||||
from the pointer target type. */
|
||||
@ -511,6 +513,10 @@ int warn_cast_qual;
|
||||
|
||||
int warn_bad_function_cast;
|
||||
|
||||
/* Warn about functions which might be candidates for attribute noreturn. */
|
||||
|
||||
int warn_missing_noreturn;
|
||||
|
||||
/* Warn about traditional constructs whose meanings changed in ANSI C. */
|
||||
|
||||
int warn_traditional;
|
||||
@ -597,19 +603,12 @@ int dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
|
||||
|
||||
int
|
||||
c_decode_option (argc, argv)
|
||||
int argc;
|
||||
int argc ATTRIBUTE_UNUSED;
|
||||
char **argv;
|
||||
{
|
||||
int strings_processed;
|
||||
char *p = argv[0];
|
||||
#if USE_CPPLIB
|
||||
if (! cpp_initialized)
|
||||
{
|
||||
cpp_reader_init (&parse_in);
|
||||
parse_in.data = &parse_options;
|
||||
cpp_options_init (&parse_options);
|
||||
cpp_initialized = 1;
|
||||
}
|
||||
strings_processed = cpp_handle_option (&parse_in, argc, argv);
|
||||
#else
|
||||
strings_processed = 0;
|
||||
@ -640,6 +639,63 @@ c_decode_option (argc, argv)
|
||||
flag_traditional = 0;
|
||||
flag_writable_strings = 0;
|
||||
}
|
||||
else if (!strncmp (p, "-std=", 5))
|
||||
{
|
||||
/* Select the appropriate language standard. We currently
|
||||
recognize:
|
||||
-std=iso9899:1990 same as -ansi
|
||||
-std=iso9899:199409 ISO C as modified in amend. 1
|
||||
-std=iso9899:199x ISO C 9x
|
||||
-std=c89 same as -std=iso9899:1990
|
||||
-std=c9x same as -std=iso9899:199x
|
||||
-std=gnu89 default, iso9899:1990 + gnu extensions
|
||||
-std=gnu9x iso9899:199x + gnu extensions
|
||||
*/
|
||||
const char *argstart = &p[5];
|
||||
|
||||
if (!strcmp (argstart, "iso9899:1990")
|
||||
|| !strcmp (argstart, "c89"))
|
||||
{
|
||||
iso_1990:
|
||||
flag_traditional = 0;
|
||||
flag_writable_strings = 0;
|
||||
flag_no_asm = 1;
|
||||
flag_no_nonansi_builtin = 1;
|
||||
flag_isoc9x = 0;
|
||||
}
|
||||
else if (!strcmp (argstart, "iso9899:199409"))
|
||||
{
|
||||
/* ??? The changes since ISO C 1990 are not supported. */
|
||||
goto iso_1990;
|
||||
}
|
||||
else if (!strcmp (argstart, "iso9899:199x")
|
||||
|| !strcmp (argstart, "c9x"))
|
||||
{
|
||||
flag_traditional = 0;
|
||||
flag_writable_strings = 0;
|
||||
flag_no_asm = 1;
|
||||
flag_no_nonansi_builtin = 1;
|
||||
flag_isoc9x = 1;
|
||||
}
|
||||
else if (!strcmp (argstart, "gnu89"))
|
||||
{
|
||||
flag_traditional = 0;
|
||||
flag_writable_strings = 0;
|
||||
flag_no_asm = 0;
|
||||
flag_no_nonansi_builtin = 0;
|
||||
flag_isoc9x = 0;
|
||||
}
|
||||
else if (!strcmp (argstart, "gnu9x"))
|
||||
{
|
||||
flag_traditional = 0;
|
||||
flag_writable_strings = 0;
|
||||
flag_no_asm = 0;
|
||||
flag_no_nonansi_builtin = 0;
|
||||
flag_isoc9x = 1;
|
||||
}
|
||||
else
|
||||
error ("unknown C standard `%s'", argstart);
|
||||
}
|
||||
else if (!strcmp (p, "-fdollars-in-identifiers"))
|
||||
dollars_in_ident = 1;
|
||||
else if (!strcmp (p, "-fno-dollars-in-identifiers"))
|
||||
@ -684,12 +740,8 @@ c_decode_option (argc, argv)
|
||||
flag_no_builtin = 0;
|
||||
else if (!strcmp (p, "-fno-builtin"))
|
||||
flag_no_builtin = 1;
|
||||
else if (!strcmp (p, "-fno-ident"))
|
||||
flag_no_ident = 1;
|
||||
else if (!strcmp (p, "-fident"))
|
||||
flag_no_ident = 0;
|
||||
else if (!strcmp (p, "-ansi"))
|
||||
flag_no_asm = 1, flag_no_nonansi_builtin = 1;
|
||||
goto iso_1990;
|
||||
else if (!strcmp (p, "-Werror-implicit-function-declaration"))
|
||||
mesg_implicit_function_declaration = 2;
|
||||
else if (!strcmp (p, "-Wimplicit-function-declaration"))
|
||||
@ -713,9 +765,9 @@ c_decode_option (argc, argv)
|
||||
else if (!strcmp (p, "-Wno-long-long"))
|
||||
warn_long_long = 0;
|
||||
else if (!strcmp (p, "-Wwrite-strings"))
|
||||
warn_write_strings = 1;
|
||||
flag_const_strings = 1;
|
||||
else if (!strcmp (p, "-Wno-write-strings"))
|
||||
warn_write_strings = 0;
|
||||
flag_const_strings = 0;
|
||||
else if (!strcmp (p, "-Wcast-qual"))
|
||||
warn_cast_qual = 1;
|
||||
else if (!strcmp (p, "-Wno-cast-qual"))
|
||||
@ -724,6 +776,10 @@ c_decode_option (argc, argv)
|
||||
warn_bad_function_cast = 1;
|
||||
else if (!strcmp (p, "-Wno-bad-function-cast"))
|
||||
warn_bad_function_cast = 0;
|
||||
else if (!strcmp (p, "-Wmissing-noreturn"))
|
||||
warn_missing_noreturn = 1;
|
||||
else if (!strcmp (p, "-Wno-missing-noreturn"))
|
||||
warn_missing_noreturn = 0;
|
||||
else if (!strcmp (p, "-Wpointer-arith"))
|
||||
warn_pointer_arith = 1;
|
||||
else if (!strcmp (p, "-Wno-pointer-arith"))
|
||||
@ -799,7 +855,7 @@ c_decode_option (argc, argv)
|
||||
else if (!strcmp (p, "-Wmain"))
|
||||
warn_main = 1;
|
||||
else if (!strcmp (p, "-Wno-main"))
|
||||
warn_main = 0;
|
||||
warn_main = -1;
|
||||
else if (!strcmp (p, "-Wsign-compare"))
|
||||
warn_sign_compare = 1;
|
||||
else if (!strcmp (p, "-Wno-sign-compare"))
|
||||
@ -942,7 +998,7 @@ kept_level_p ()
|
||||
|
||||
void
|
||||
declare_parm_level (definition_flag)
|
||||
int definition_flag;
|
||||
int definition_flag ATTRIBUTE_UNUSED;
|
||||
{
|
||||
current_binding_level->parm_flag = 1;
|
||||
}
|
||||
@ -1059,24 +1115,22 @@ poplevel (keep, reverse, functionbody)
|
||||
if (TYPE_SIZE (TREE_VALUE (link)) == 0)
|
||||
{
|
||||
tree type = TREE_VALUE (link);
|
||||
char *errmsg;
|
||||
tree type_name = TYPE_NAME (type);
|
||||
char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
|
||||
? type_name
|
||||
: DECL_NAME (type_name));
|
||||
switch (TREE_CODE (type))
|
||||
{
|
||||
case RECORD_TYPE:
|
||||
errmsg = "`struct %s' incomplete in scope ending here";
|
||||
error ("`struct %s' incomplete in scope ending here", id);
|
||||
break;
|
||||
case UNION_TYPE:
|
||||
errmsg = "`union %s' incomplete in scope ending here";
|
||||
error ("`union %s' incomplete in scope ending here", id);
|
||||
break;
|
||||
case ENUMERAL_TYPE:
|
||||
errmsg = "`enum %s' incomplete in scope ending here";
|
||||
error ("`enum %s' incomplete in scope ending here", id);
|
||||
break;
|
||||
}
|
||||
if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
|
||||
error (errmsg, IDENTIFIER_POINTER (TYPE_NAME (type)));
|
||||
else
|
||||
/* If this type has a typedef-name, the TYPE_NAME is a TYPE_DECL. */
|
||||
error (errmsg, IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))));
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
@ -1456,7 +1510,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
&& DECL_INITIAL (newdecl) != 0);
|
||||
tree oldtype = TREE_TYPE (olddecl);
|
||||
tree newtype = TREE_TYPE (newdecl);
|
||||
char *errmsg = 0;
|
||||
int errmsg = 0;
|
||||
|
||||
if (TREE_CODE_CLASS (TREE_CODE (olddecl)) == 'd')
|
||||
DECL_MACHINE_ATTRIBUTES (newdecl)
|
||||
@ -1683,16 +1737,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
if (TREE_CHAIN (t) == 0
|
||||
&& TYPE_MAIN_VARIANT (type) != void_type_node)
|
||||
{
|
||||
error ("A parameter list with an ellipsis can't match");
|
||||
error ("an empty parameter name list declaration.");
|
||||
error ("A parameter list with an ellipsis can't match an empty parameter name list declaration.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (TYPE_MAIN_VARIANT (type) == float_type_node
|
||||
|| C_PROMOTING_INTEGER_TYPE_P (type))
|
||||
{
|
||||
error ("An argument type that has a default promotion");
|
||||
error ("can't match an empty parameter name list declaration.");
|
||||
error ("An argument type that has a default promotion can't match an empty parameter name list declaration.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1704,7 +1756,21 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
errmsg = redeclaration_error_message (newdecl, olddecl);
|
||||
if (errmsg)
|
||||
{
|
||||
error_with_decl (newdecl, errmsg);
|
||||
switch (errmsg)
|
||||
{
|
||||
case 1:
|
||||
error_with_decl (newdecl, "redefinition of `%s'");
|
||||
break;
|
||||
case 2:
|
||||
error_with_decl (newdecl, "redeclaration of `%s'");
|
||||
break;
|
||||
case 3:
|
||||
error_with_decl (newdecl, "conflicting declarations of `%s'");
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
error_with_decl (olddecl,
|
||||
((DECL_INITIAL (olddecl)
|
||||
&& current_binding_level == global_binding_level)
|
||||
@ -1736,14 +1802,22 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
|
||||
type = TYPE_ARG_TYPES (newtype),
|
||||
nargs = 1;
|
||||
(TYPE_MAIN_VARIANT (TREE_VALUE (parm)) != void_type_node
|
||||
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) != void_type_node);
|
||||
;
|
||||
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
|
||||
{
|
||||
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|
||||
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
|
||||
{
|
||||
warning_with_decl (newdecl, "prototype for `%s' follows");
|
||||
warning_with_decl (olddecl, "non-prototype definition here");
|
||||
break;
|
||||
}
|
||||
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|
||||
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
|
||||
{
|
||||
errmsg = "prototype for `%s' follows and number of arguments";
|
||||
error_with_decl (newdecl, "prototype for `%s' follows and number of arguments doesn't match");
|
||||
error_with_decl (olddecl, "non-prototype definition here");
|
||||
errmsg = 1;
|
||||
break;
|
||||
}
|
||||
/* Type for passing arg must be consistent
|
||||
@ -1755,21 +1829,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
&& TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == integer_type_node
|
||||
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == unsigned_type_node)))
|
||||
{
|
||||
errmsg = "prototype for `%s' follows and argument %d";
|
||||
error_with_decl (newdecl,
|
||||
"prototype for `%s' follows and argument %d doesn't match",
|
||||
nargs);
|
||||
error_with_decl (olddecl, "non-prototype definition here");
|
||||
errmsg = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (errmsg)
|
||||
{
|
||||
error_with_decl (newdecl, errmsg, nargs);
|
||||
error_with_decl (olddecl,
|
||||
"doesn't match non-prototype definition here");
|
||||
}
|
||||
else
|
||||
{
|
||||
warning_with_decl (newdecl, "prototype for `%s' follows");
|
||||
warning_with_decl (olddecl, "non-prototype definition here");
|
||||
}
|
||||
}
|
||||
/* Warn about mismatches in various flags. */
|
||||
else
|
||||
@ -1794,6 +1861,14 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
&& !TREE_PUBLIC (newdecl))
|
||||
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
|
||||
|
||||
/* If warn_traditional, warn when a non-static function
|
||||
declaration follows a static one. */
|
||||
if (warn_traditional
|
||||
&& TREE_CODE (olddecl) == FUNCTION_DECL
|
||||
&& !TREE_PUBLIC (olddecl)
|
||||
&& TREE_PUBLIC (newdecl))
|
||||
warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
|
||||
|
||||
/* Warn when const declaration follows a non-const
|
||||
declaration, but not for functions. */
|
||||
if (TREE_CODE (olddecl) != FUNCTION_DECL
|
||||
@ -1931,6 +2006,11 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
{
|
||||
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
|
||||
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
|
||||
|
||||
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|
||||
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
|
||||
DECL_NO_CHECK_MEMORY_USAGE (newdecl)
|
||||
|= DECL_NO_CHECK_MEMORY_USAGE (olddecl);
|
||||
}
|
||||
|
||||
pop_obstacks ();
|
||||
@ -2017,7 +2097,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
|
||||
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
|
||||
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
|
||||
if (DECL_INLINE (newdecl))
|
||||
DECL_ABSTRACT_ORIGIN (newdecl) = olddecl;
|
||||
DECL_ABSTRACT_ORIGIN (newdecl) = DECL_ORIGIN (olddecl);
|
||||
}
|
||||
}
|
||||
if (different_binding_level)
|
||||
@ -2381,7 +2461,7 @@ pushdecl (x)
|
||||
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
|
||||
DECL_RESULT (x) = DECL_RESULT (oldglobal);
|
||||
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
|
||||
DECL_ABSTRACT_ORIGIN (x) = oldglobal;
|
||||
DECL_ABSTRACT_ORIGIN (x) = DECL_ORIGIN (oldglobal);
|
||||
}
|
||||
/* Inner extern decl is built-in if global one is. */
|
||||
if (DECL_BUILT_IN (oldglobal))
|
||||
@ -2454,7 +2534,7 @@ pushdecl (x)
|
||||
/* No shadow warnings for vars made for inlining. */
|
||||
&& ! DECL_FROM_INLINE (x))
|
||||
{
|
||||
char *warnstring = 0;
|
||||
char *id = IDENTIFIER_POINTER (name);
|
||||
|
||||
if (TREE_CODE (x) == PARM_DECL
|
||||
&& current_binding_level->level_chain->parm_flag)
|
||||
@ -2465,15 +2545,12 @@ pushdecl (x)
|
||||
but there is no way to tell it's not a definition. */
|
||||
;
|
||||
else if (oldlocal != 0 && TREE_CODE (oldlocal) == PARM_DECL)
|
||||
warnstring = "declaration of `%s' shadows a parameter";
|
||||
warning ("declaration of `%s' shadows a parameter", id);
|
||||
else if (oldlocal != 0)
|
||||
warnstring = "declaration of `%s' shadows previous local";
|
||||
warning ("declaration of `%s' shadows previous local", id);
|
||||
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
|
||||
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
|
||||
warnstring = "declaration of `%s' shadows global declaration";
|
||||
|
||||
if (warnstring)
|
||||
warning (warnstring, IDENTIFIER_POINTER (name));
|
||||
warning ("declaration of `%s' shadows global declaration", id);
|
||||
}
|
||||
|
||||
/* If storing a local value, there may already be one (inherited).
|
||||
@ -2584,10 +2661,10 @@ implicitly_declare (functionid)
|
||||
/* Return zero if the declaration NEWDECL is valid
|
||||
when the declaration OLDDECL (assumed to be for the same name)
|
||||
has already been seen.
|
||||
Otherwise return an error message format string with a %s
|
||||
where the identifier should go. */
|
||||
Otherwise return 1 if NEWDECL is a redefinition, 2 if it is a redeclaration,
|
||||
and 3 if it is a conflicting declaration. */
|
||||
|
||||
static char *
|
||||
static int
|
||||
redeclaration_error_message (newdecl, olddecl)
|
||||
tree newdecl, olddecl;
|
||||
{
|
||||
@ -2606,7 +2683,7 @@ redeclaration_error_message (newdecl, olddecl)
|
||||
return 0;
|
||||
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
|
||||
return 0;
|
||||
return "redefinition of `%s'";
|
||||
return 1;
|
||||
}
|
||||
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
|
||||
{
|
||||
@ -2619,7 +2696,7 @@ redeclaration_error_message (newdecl, olddecl)
|
||||
time in another way is ok. */
|
||||
&& !(DECL_INLINE (olddecl) && DECL_EXTERNAL (olddecl)
|
||||
&& !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
|
||||
return "redefinition of `%s'";
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
else if (current_binding_level == global_binding_level)
|
||||
@ -2630,11 +2707,11 @@ redeclaration_error_message (newdecl, olddecl)
|
||||
return 0;
|
||||
/* Reject two definitions. */
|
||||
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
|
||||
return "redefinition of `%s'";
|
||||
return 1;
|
||||
/* Now we have two tentative defs, or one tentative and one real def. */
|
||||
/* Insist that the linkage match. */
|
||||
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
|
||||
return "conflicting declarations of `%s'";
|
||||
return 3;
|
||||
return 0;
|
||||
}
|
||||
else if (current_binding_level->parm_flag
|
||||
@ -2648,7 +2725,7 @@ redeclaration_error_message (newdecl, olddecl)
|
||||
be an extern reference to olddecl. */
|
||||
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
|
||||
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
|
||||
return "redeclaration of `%s'";
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -3038,8 +3115,10 @@ init_decl_processing ()
|
||||
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
|
||||
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
|
||||
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
|
||||
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
|
||||
#endif
|
||||
|
||||
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
|
||||
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
|
||||
@ -3053,8 +3132,10 @@ init_decl_processing ()
|
||||
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
|
||||
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
|
||||
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
|
||||
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
|
||||
#endif
|
||||
|
||||
float_type_node = make_node (REAL_TYPE);
|
||||
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
|
||||
@ -3288,8 +3369,8 @@ init_decl_processing ()
|
||||
builtin_function ("__builtin_unwind_init",
|
||||
build_function_type (void_type_node, endlink),
|
||||
BUILT_IN_UNWIND_INIT, NULL_PTR);
|
||||
builtin_function ("__builtin_fp", ptr_ftype_void, BUILT_IN_FP, NULL_PTR);
|
||||
builtin_function ("__builtin_sp", ptr_ftype_void, BUILT_IN_SP, NULL_PTR);
|
||||
builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
|
||||
BUILT_IN_DWARF_CFA, NULL_PTR);
|
||||
builtin_function ("__builtin_dwarf_fp_regnum",
|
||||
build_function_type (unsigned_type_node, endlink),
|
||||
BUILT_IN_DWARF_FP_REGNUM, NULL_PTR);
|
||||
@ -3299,24 +3380,16 @@ init_decl_processing ()
|
||||
BUILT_IN_FROB_RETURN_ADDR, NULL_PTR);
|
||||
builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
|
||||
BUILT_IN_EXTRACT_RETURN_ADDR, NULL_PTR);
|
||||
builtin_function ("__builtin_set_return_addr_reg",
|
||||
build_function_type (void_type_node,
|
||||
tree_cons (NULL_TREE,
|
||||
ptr_type_node,
|
||||
endlink)),
|
||||
BUILT_IN_SET_RETURN_ADDR_REG, NULL_PTR);
|
||||
builtin_function ("__builtin_eh_stub_old", ptr_ftype_void,
|
||||
BUILT_IN_EH_STUB_OLD, NULL_PTR);
|
||||
builtin_function ("__builtin_eh_stub", ptr_ftype_void,
|
||||
BUILT_IN_EH_STUB, NULL_PTR);
|
||||
builtin_function
|
||||
("__builtin_set_eh_regs",
|
||||
("__builtin_eh_return",
|
||||
build_function_type (void_type_node,
|
||||
tree_cons (NULL_TREE, ptr_type_node,
|
||||
tree_cons (NULL_TREE,
|
||||
type_for_mode (ptr_mode, 0),
|
||||
endlink))),
|
||||
BUILT_IN_SET_EH_REGS, NULL_PTR);
|
||||
tree_cons (NULL_TREE,
|
||||
ptr_type_node,
|
||||
endlink)))),
|
||||
BUILT_IN_EH_RETURN, NULL_PTR);
|
||||
|
||||
builtin_function ("__builtin_alloca",
|
||||
build_function_type (ptr_type_node,
|
||||
@ -3530,7 +3603,7 @@ init_decl_processing ()
|
||||
|
||||
incomplete_decl_finalize_hook = finish_incomplete_decl;
|
||||
|
||||
lang_get_alias_set = &c_get_alias_set;
|
||||
lang_get_alias_set = c_get_alias_set;
|
||||
}
|
||||
|
||||
/* Return a definition for a builtin function named NAME and whose data type
|
||||
@ -3543,10 +3616,10 @@ init_decl_processing ()
|
||||
|
||||
tree
|
||||
builtin_function (name, type, function_code, library_name)
|
||||
char *name;
|
||||
const char *name;
|
||||
tree type;
|
||||
enum built_in_function function_code;
|
||||
char *library_name;
|
||||
const char *library_name;
|
||||
{
|
||||
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
@ -3718,7 +3791,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
|
||||
/* The corresponding pop_obstacks is in finish_decl. */
|
||||
push_obstacks_nochange ();
|
||||
|
||||
if (warn_main && TREE_CODE (decl) != FUNCTION_DECL
|
||||
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
|
||||
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "main"))
|
||||
warning_with_decl (decl, "`%s' is usually a function");
|
||||
|
||||
@ -4309,13 +4382,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
tree type = NULL_TREE;
|
||||
int longlong = 0;
|
||||
int constp;
|
||||
int restrictp;
|
||||
int volatilep;
|
||||
int type_quals = TYPE_UNQUALIFIED;
|
||||
int inlinep;
|
||||
int explicit_int = 0;
|
||||
int explicit_char = 0;
|
||||
int defaulted_int = 0;
|
||||
tree typedef_decl = 0;
|
||||
char *name;
|
||||
const char *name;
|
||||
tree typedef_type = 0;
|
||||
int funcdef_flag = 0;
|
||||
enum tree_code innermost_code = ERROR_MARK;
|
||||
@ -4471,13 +4546,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
|
||||
&& ! (in_system_header && ! allocation_temporary_p ()))
|
||||
{
|
||||
/* C9x will probably require a diagnostic here.
|
||||
For now, issue a warning if -Wreturn-type and this is a function,
|
||||
or if -Wimplicit; prefer the former warning since it is more
|
||||
explicit. */
|
||||
/* Issue a warning if this is an ISO C 9x program or if -Wreturn-type
|
||||
and this is a function, or if -Wimplicit; prefer the former
|
||||
warning since it is more explicit. */
|
||||
if ((warn_implicit_int || warn_return_type) && funcdef_flag)
|
||||
warn_about_return_type = 1;
|
||||
else if (warn_implicit_int)
|
||||
else if (warn_implicit_int || flag_isoc9x)
|
||||
warning ("type defaults to `int' in declaration of `%s'", name);
|
||||
}
|
||||
|
||||
@ -4619,19 +4693,26 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
type = build_complex_type (type);
|
||||
}
|
||||
|
||||
/* Set CONSTP if this declaration is `const', whether by
|
||||
explicit specification or via a typedef.
|
||||
Likewise for VOLATILEP. */
|
||||
|
||||
/* Figure out the type qualifiers for the declaration. There are
|
||||
two ways a declaration can become qualified. One is something
|
||||
like `const int i' where the `const' is explicit. Another is
|
||||
something like `typedef const int CI; CI i' where the type of the
|
||||
declaration contains the `const'. */
|
||||
constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
|
||||
restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
|
||||
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
|
||||
inlinep = !! (specbits & (1 << (int) RID_INLINE));
|
||||
if (constp > 1)
|
||||
pedwarn ("duplicate `const'");
|
||||
if (restrictp > 1)
|
||||
pedwarn ("duplicate `restrict'");
|
||||
if (volatilep > 1)
|
||||
pedwarn ("duplicate `volatile'");
|
||||
if (! flag_gen_aux_info && (TYPE_READONLY (type) || TYPE_VOLATILE (type)))
|
||||
if (! flag_gen_aux_info && (TYPE_QUALS (type)))
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
|
||||
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
|
||||
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
|
||||
|
||||
/* Warn if two storage classes are given. Default to `auto'. */
|
||||
|
||||
@ -4865,13 +4946,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
is set correctly. */
|
||||
|
||||
type = build_array_type (type, itype);
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
|
||||
#if 0 /* don't clear these; leave them set so that the array type
|
||||
or the variable is itself const or volatile. */
|
||||
constp = 0;
|
||||
volatilep = 0;
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
#endif
|
||||
|
||||
if (size_varies)
|
||||
@ -4936,12 +5016,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
flag_traditional
|
||||
? NULL_TREE : arg_types);
|
||||
#endif
|
||||
/* ANSI seems to say that `const int foo ();'
|
||||
does not make the function foo const. */
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
constp = 0;
|
||||
volatilep = 0;
|
||||
/* Type qualifiers before the return type of the function
|
||||
qualify the return type, not the function type. */
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
|
||||
type = build_function_type (type, arg_types);
|
||||
declarator = TREE_OPERAND (declarator, 0);
|
||||
@ -4965,12 +5044,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
for the pointer. */
|
||||
|
||||
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
|
||||
&& (constp || volatilep))
|
||||
pedwarn ("ANSI C forbids const or volatile function types");
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
constp = 0;
|
||||
volatilep = 0;
|
||||
&& type_quals)
|
||||
pedwarn ("ANSI C forbids qualified function types");
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
size_varies = 0;
|
||||
|
||||
type = build_pointer_type (type);
|
||||
@ -4982,13 +5060,21 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
{
|
||||
register tree typemodlist;
|
||||
int erred = 0;
|
||||
|
||||
constp = 0;
|
||||
volatilep = 0;
|
||||
restrictp = 0;
|
||||
for (typemodlist = TREE_TYPE (declarator); typemodlist;
|
||||
typemodlist = TREE_CHAIN (typemodlist))
|
||||
{
|
||||
if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_CONST])
|
||||
tree qualifier = TREE_VALUE (typemodlist);
|
||||
|
||||
if (qualifier == ridpointers[(int) RID_CONST])
|
||||
constp++;
|
||||
else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_VOLATILE])
|
||||
else if (qualifier == ridpointers[(int) RID_VOLATILE])
|
||||
volatilep++;
|
||||
else if (qualifier == ridpointers[(int) RID_RESTRICT])
|
||||
restrictp++;
|
||||
else if (!erred)
|
||||
{
|
||||
erred = 1;
|
||||
@ -4999,6 +5085,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
pedwarn ("duplicate `const'");
|
||||
if (volatilep > 1)
|
||||
pedwarn ("duplicate `volatile'");
|
||||
if (restrictp > 1)
|
||||
pedwarn ("duplicate `restrict'");
|
||||
|
||||
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
|
||||
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
|
||||
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
|
||||
}
|
||||
|
||||
declarator = TREE_OPERAND (declarator, 0);
|
||||
@ -5025,10 +5117,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
/* Note that the grammar rejects storage classes
|
||||
in typenames, fields or parameters */
|
||||
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
|
||||
&& (constp || volatilep))
|
||||
pedwarn ("ANSI C forbids const or volatile function types");
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
&& type_quals)
|
||||
pedwarn ("ANSI C forbids qualified function types");
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
decl = build_decl (TYPE_DECL, declarator, type);
|
||||
if ((specbits & (1 << (int) RID_SIGNED))
|
||||
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
|
||||
@ -5060,10 +5152,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
/* Note that the grammar rejects storage classes
|
||||
in typenames, fields or parameters */
|
||||
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
|
||||
&& (constp || volatilep))
|
||||
&& type_quals)
|
||||
pedwarn ("ANSI C forbids const or volatile function types");
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
pop_obstacks ();
|
||||
return type;
|
||||
}
|
||||
@ -5103,20 +5195,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
{
|
||||
/* Transfer const-ness of array into that of type pointed to. */
|
||||
type = TREE_TYPE (type);
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
type = build_pointer_type (type);
|
||||
volatilep = constp = 0;
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
size_varies = 0;
|
||||
}
|
||||
else if (TREE_CODE (type) == FUNCTION_TYPE)
|
||||
{
|
||||
if (pedantic && (constp || volatilep))
|
||||
pedwarn ("ANSI C forbids const or volatile function types");
|
||||
if (constp || volatilep)
|
||||
type = c_build_type_variant (type, constp, volatilep);
|
||||
if (pedantic && type_quals)
|
||||
pedwarn ("ANSI C forbids qualified function types");
|
||||
if (type_quals)
|
||||
type = c_build_qualified_type (type, type_quals);
|
||||
type = build_pointer_type (type);
|
||||
volatilep = constp = 0;
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
}
|
||||
|
||||
decl = build_decl (PARM_DECL, declarator, type);
|
||||
@ -5164,13 +5256,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
type = error_mark_node;
|
||||
}
|
||||
/* Move type qualifiers down to element of an array. */
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
|
||||
{
|
||||
type = build_array_type (c_build_type_variant (TREE_TYPE (type),
|
||||
constp, volatilep),
|
||||
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
|
||||
type_quals),
|
||||
TYPE_DOMAIN (type));
|
||||
#if 0 /* Leave the field const or volatile as well. */
|
||||
constp = volatilep = 0;
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
#endif
|
||||
}
|
||||
decl = build_decl (FIELD_DECL, declarator, type);
|
||||
@ -5209,18 +5301,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
decl = build_decl (FUNCTION_DECL, declarator, type);
|
||||
decl = build_decl_attribute_variant (decl, decl_machine_attr);
|
||||
|
||||
if (pedantic && (constp || volatilep)
|
||||
&& ! DECL_IN_SYSTEM_HEADER (decl))
|
||||
pedwarn ("ANSI C forbids const or volatile functions");
|
||||
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
|
||||
pedwarn ("ANSI C forbids qualified function types");
|
||||
|
||||
if (pedantic
|
||||
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl))) == void_type_node
|
||||
&& (TYPE_READONLY (TREE_TYPE (TREE_TYPE (decl)))
|
||||
|| TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (decl))))
|
||||
&& TYPE_QUALS (TREE_TYPE (TREE_TYPE (decl)))
|
||||
&& ! DECL_IN_SYSTEM_HEADER (decl))
|
||||
pedwarn ("ANSI C forbids const or volatile void function return type");
|
||||
pedwarn ("ANSI C forbids qualified void function return type");
|
||||
|
||||
if (volatilep
|
||||
/* GNU C interprets a `volatile void' return type to indicate
|
||||
that the function does not return. */
|
||||
if ((type_quals & TYPE_QUAL_VOLATILE)
|
||||
&& TREE_TYPE (TREE_TYPE (decl)) != void_type_node)
|
||||
warning ("`noreturn' function returns non-void value");
|
||||
|
||||
@ -5250,13 +5342,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
|
||||
|
||||
/* Move type qualifiers down to element of an array. */
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && (constp || volatilep))
|
||||
if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
|
||||
{
|
||||
type = build_array_type (c_build_type_variant (TREE_TYPE (type),
|
||||
constp, volatilep),
|
||||
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
|
||||
type_quals),
|
||||
TYPE_DOMAIN (type));
|
||||
#if 0 /* Leave the variable const or volatile as well. */
|
||||
constp = volatilep = 0;
|
||||
type_quals = TYPE_UNQUALIFIED;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -5303,14 +5395,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
|
||||
DECL_REGISTER (decl) = 1;
|
||||
|
||||
/* Record constancy and volatility. */
|
||||
c_apply_type_quals_to_decl (type_quals, decl);
|
||||
|
||||
if (constp)
|
||||
TREE_READONLY (decl) = 1;
|
||||
if (volatilep)
|
||||
{
|
||||
TREE_SIDE_EFFECTS (decl) = 1;
|
||||
TREE_THIS_VOLATILE (decl) = 1;
|
||||
}
|
||||
/* If a type has volatile components, it should be stored in memory.
|
||||
Otherwise, the fact that those components are volatile
|
||||
will be ignored, and would even crash the compiler. */
|
||||
@ -5570,8 +5656,7 @@ parmlist_tags_warning ()
|
||||
|
||||
if (! already)
|
||||
{
|
||||
warning ("its scope is only this definition or declaration,");
|
||||
warning ("which is probably not what you want.");
|
||||
warning ("its scope is only this definition or declaration, which is probably not what you want.");
|
||||
already = 1;
|
||||
}
|
||||
}
|
||||
@ -5685,8 +5770,8 @@ start_struct (code, name)
|
||||
|
||||
tree
|
||||
grokfield (filename, line, declarator, declspecs, width)
|
||||
char *filename;
|
||||
int line;
|
||||
const char *filename ATTRIBUTE_UNUSED;
|
||||
int line ATTRIBUTE_UNUSED;
|
||||
tree declarator, declspecs, width;
|
||||
{
|
||||
tree value;
|
||||
@ -5768,9 +5853,10 @@ finish_struct (t, fieldlist, attributes)
|
||||
break;
|
||||
|
||||
if (x == 0)
|
||||
pedwarn ("%s has no %smembers",
|
||||
(TREE_CODE (t) == UNION_TYPE ? "union" : "structure"),
|
||||
(fieldlist ? "named " : ""));
|
||||
pedwarn ((fieldlist
|
||||
? "%s has no named members"
|
||||
: "%s has no members"),
|
||||
TREE_CODE (t) == UNION_TYPE ? "union" : "struct");
|
||||
}
|
||||
|
||||
/* Install struct as DECL_CONTEXT of each field decl.
|
||||
@ -6428,6 +6514,10 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
|
||||
except for defining how to inline. So set DECL_EXTERNAL in that case. */
|
||||
DECL_EXTERNAL (decl1) = current_extern_inline;
|
||||
|
||||
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
|
||||
SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
|
||||
#endif
|
||||
|
||||
/* This function exists in static storage.
|
||||
(This does not mean `static' in the C sense!) */
|
||||
TREE_STATIC (decl1) = 1;
|
||||
@ -6437,7 +6527,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes, nested)
|
||||
TREE_PUBLIC (decl1) = 0;
|
||||
|
||||
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
|
||||
if (warn_main
|
||||
if (warn_main > 0
|
||||
&& strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
|
||||
{
|
||||
tree args;
|
||||
@ -7154,12 +7244,8 @@ finish_function (nested)
|
||||
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
|
||||
!= integer_type_node)
|
||||
{
|
||||
/* You would expect the sense of this test to be the other way
|
||||
around, but if warn_main is set, we will already have warned,
|
||||
so this would be a duplicate. This is the warning you get
|
||||
in some environments even if you *don't* ask for it, because
|
||||
these are environments where it may be more of a problem than
|
||||
usual. */
|
||||
/* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
|
||||
If warn_main is -1 (-Wno-main) we don't want to be warned. */
|
||||
if (! warn_main)
|
||||
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
|
||||
}
|
||||
@ -7183,6 +7269,12 @@ finish_function (nested)
|
||||
|
||||
current_function_returns_null |= can_reach_end;
|
||||
|
||||
if (warn_missing_noreturn
|
||||
&& !TREE_THIS_VOLATILE (fndecl)
|
||||
&& !current_function_returns_null
|
||||
&& !current_function_returns_value)
|
||||
warning ("function might be possible candidate for attribute `noreturn'");
|
||||
|
||||
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
|
||||
warning ("`noreturn' function does return");
|
||||
else if (warn_return_type && can_reach_end
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Build expressions with type checking for C compiler.
|
||||
Copyright (C) 1987, 88, 89, 92, 93, 96, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 88, 89, 92, 93, 96, 1997, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -539,10 +539,10 @@ prdecl (d)
|
||||
fprintf (stderr, dname);
|
||||
}
|
||||
else
|
||||
fprintf (stderr, "<<Not a Decl!!!>>");
|
||||
fprintf (stderr, "<<?>>");
|
||||
}
|
||||
else
|
||||
fprintf (stderr, "<<NULL!!>>");
|
||||
fprintf (stderr, "<<0>>");
|
||||
}
|
||||
|
||||
/* Print Iterator List -- names only */
|
||||
|
@ -28,6 +28,13 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "toplev.h"
|
||||
#include "output.h"
|
||||
|
||||
#if USE_CPPLIB
|
||||
#include "cpplib.h"
|
||||
extern char *yy_cur;
|
||||
extern cpp_reader parse_in;
|
||||
extern cpp_options parse_options;
|
||||
#endif
|
||||
|
||||
/* Each of the functions defined here
|
||||
is an alternative to a function in objc-actions.c. */
|
||||
|
||||
@ -42,17 +49,25 @@ lang_decode_option (argc, argv)
|
||||
void
|
||||
lang_init_options ()
|
||||
{
|
||||
#if USE_CPPLIB
|
||||
cpp_reader_init (&parse_in);
|
||||
parse_in.opts = &parse_options;
|
||||
cpp_options_init (&parse_options);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
lang_init ()
|
||||
{
|
||||
#if !USE_CPPLIB
|
||||
/* the beginning of the file is a new line; check for # */
|
||||
/* With luck, we discover the real source file's name from that
|
||||
and put it in input_filename. */
|
||||
#if !USE_CPPLIB
|
||||
ungetc (check_newline (), finput);
|
||||
#endif
|
||||
#else
|
||||
check_newline ();
|
||||
yy_cur--;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@ -134,7 +149,7 @@ recognize_objc_keyword ()
|
||||
tree
|
||||
build_objc_string (len, str)
|
||||
int len ATTRIBUTE_UNUSED;
|
||||
char *str ATTRIBUTE_UNUSED;
|
||||
const char *str ATTRIBUTE_UNUSED;
|
||||
{
|
||||
abort ();
|
||||
return NULL_TREE;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Define constants for communication with c-parse.y.
|
||||
Copyright (C) 1987, 1992 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 1992, 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -40,6 +40,7 @@ enum rid
|
||||
RID_TYPEDEF,
|
||||
RID_SIGNED,
|
||||
RID_CONST,
|
||||
RID_RESTRICT,
|
||||
RID_VOLATILE,
|
||||
RID_INLINE,
|
||||
RID_NOALIAS,
|
||||
@ -50,6 +51,7 @@ enum rid
|
||||
RID_OUT,
|
||||
RID_INOUT,
|
||||
RID_BYCOPY,
|
||||
RID_BYREF,
|
||||
RID_ONEWAY,
|
||||
RID_ID,
|
||||
|
||||
@ -79,7 +81,7 @@ extern void position_after_white_space PROTO((void));
|
||||
extern int check_newline PROTO((void));
|
||||
|
||||
extern int yylex PROTO((void));
|
||||
extern void yyerror PROTO((char *));
|
||||
extern void yyerror PROTO((const char *));
|
||||
|
||||
extern void forget_protocol_qualifiers PROTO((void));
|
||||
extern void remember_protocol_qualifiers PROTO((void));
|
||||
|
@ -1,7 +1,7 @@
|
||||
%{
|
||||
/* Command-line: gperf -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
|
||||
/* Command-line: gperf -L KR-C -F ', 0, 0' -p -j1 -i 1 -g -o -t -N is_reserved_word -k1,3,$ c-parse.gperf */
|
||||
%}
|
||||
struct resword { char *name; short token; enum rid rid; };
|
||||
struct resword { const char *name; short token; enum rid rid; };
|
||||
%%
|
||||
@class, CLASS, NORID
|
||||
@compatibility_alias, ALIAS, NORID
|
||||
@ -35,6 +35,8 @@ __iterator__, SCSPEC, RID_ITERATOR
|
||||
__label__, LABEL, NORID
|
||||
__real, REALPART, NORID
|
||||
__real__, REALPART, NORID
|
||||
__restrict, TYPE_QUAL, RID_RESTRICT
|
||||
__restrict__, TYPE_QUAL, RID_RESTRICT
|
||||
__signed, TYPESPEC, RID_SIGNED
|
||||
__signed__, TYPESPEC, RID_SIGNED
|
||||
__typeof, TYPEOF, NORID
|
||||
@ -45,6 +47,7 @@ asm, ASM_KEYWORD, NORID
|
||||
auto, SCSPEC, RID_AUTO
|
||||
break, BREAK, NORID
|
||||
bycopy, TYPE_QUAL, RID_BYCOPY
|
||||
byref, TYPE_QUAL, RID_BYREF
|
||||
case, CASE, NORID
|
||||
char, TYPESPEC, RID_CHAR
|
||||
const, TYPE_QUAL, RID_CONST
|
||||
@ -68,6 +71,7 @@ long, TYPESPEC, RID_LONG
|
||||
oneway, TYPE_QUAL, RID_ONEWAY
|
||||
out, TYPE_QUAL, RID_OUT
|
||||
register, SCSPEC, RID_REGISTER
|
||||
restrict, TYPE_QUAL, RID_RESTRICT
|
||||
return, RETURN, NORID
|
||||
short, TYPESPEC, RID_SHORT
|
||||
signed, TYPESPEC, RID_SIGNED
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* YACC parser for C syntax and for Objective C. -*-c-*-
|
||||
Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -31,7 +31,7 @@ ifobjc
|
||||
%expect 66
|
||||
end ifobjc
|
||||
ifc
|
||||
%expect 46
|
||||
%expect 51
|
||||
|
||||
/* These are the 23 conflicts you should get in parse.output;
|
||||
the state numbers may vary if minor changes in the grammar are made.
|
||||
@ -116,7 +116,7 @@ end ifc
|
||||
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
||||
%token TYPESPEC
|
||||
|
||||
/* Reserved words that qualify type: "const" or "volatile".
|
||||
/* Reserved words that qualify type: "const", "volatile", or "restrict".
|
||||
yylval contains an IDENTIFIER_NODE which indicates which one. */
|
||||
%token TYPE_QUAL
|
||||
|
||||
@ -525,7 +525,7 @@ cast_expr:
|
||||
tree type = $2;
|
||||
finish_init ();
|
||||
|
||||
if (pedantic)
|
||||
if (pedantic && ! flag_isoc9x)
|
||||
pedwarn ("ANSI C forbids constructor expressions");
|
||||
if (TYPE_NAME (type) != 0)
|
||||
{
|
||||
@ -604,12 +604,22 @@ expr_no_commas:
|
||||
{ skip_evaluation -= $1 == boolean_true_node;
|
||||
$$ = build_conditional_expr ($1, $<ttype>2, $5); }
|
||||
| expr_no_commas '=' expr_no_commas
|
||||
{ $$ = build_modify_expr ($1, NOP_EXPR, $3);
|
||||
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR); }
|
||||
{ char class;
|
||||
$$ = build_modify_expr ($1, NOP_EXPR, $3);
|
||||
class = TREE_CODE_CLASS (TREE_CODE ($$));
|
||||
if (class == 'e' || class == '1'
|
||||
|| class == '2' || class == '<')
|
||||
C_SET_EXP_ORIGINAL_CODE ($$, MODIFY_EXPR);
|
||||
}
|
||||
| expr_no_commas ASSIGN expr_no_commas
|
||||
{ $$ = build_modify_expr ($1, $2, $3);
|
||||
{ char class;
|
||||
$$ = build_modify_expr ($1, $2, $3);
|
||||
/* This inhibits warnings in truthvalue_conversion. */
|
||||
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK); }
|
||||
class = TREE_CODE_CLASS (TREE_CODE ($$));
|
||||
if (class == 'e' || class == '1'
|
||||
|| class == '2' || class == '<')
|
||||
C_SET_EXP_ORIGINAL_CODE ($$, ERROR_MARK);
|
||||
}
|
||||
;
|
||||
|
||||
primary:
|
||||
@ -1275,33 +1285,41 @@ initlist1:
|
||||
/* `initelt' is a single element of an initializer.
|
||||
It may use braces. */
|
||||
initelt:
|
||||
expr_no_commas
|
||||
{ process_init_element ($1); }
|
||||
| '{'
|
||||
designator_list '=' initval
|
||||
| designator initval
|
||||
| identifier ':'
|
||||
{ set_init_label ($1); }
|
||||
initval
|
||||
| initval
|
||||
;
|
||||
|
||||
initval:
|
||||
'{'
|
||||
{ push_init_level (0); }
|
||||
initlist_maybe_comma '}'
|
||||
{ process_init_element (pop_init_level (0)); }
|
||||
| expr_no_commas
|
||||
{ process_init_element ($1); }
|
||||
| error
|
||||
;
|
||||
|
||||
designator_list:
|
||||
designator
|
||||
| designator_list designator
|
||||
;
|
||||
|
||||
designator:
|
||||
'.' identifier
|
||||
{ set_init_label ($2); }
|
||||
/* These are for labeled elements. The syntax for an array element
|
||||
initializer conflicts with the syntax for an Objective-C message,
|
||||
so don't include these productions in the Objective-C grammar. */
|
||||
ifc
|
||||
| '[' expr_no_commas ELLIPSIS expr_no_commas ']' '='
|
||||
| '[' expr_no_commas ELLIPSIS expr_no_commas ']'
|
||||
{ set_init_index ($2, $4); }
|
||||
initelt
|
||||
| '[' expr_no_commas ']' '='
|
||||
{ set_init_index ($2, NULL_TREE); }
|
||||
initelt
|
||||
| '[' expr_no_commas ']'
|
||||
{ set_init_index ($2, NULL_TREE); }
|
||||
initelt
|
||||
end ifc
|
||||
| identifier ':'
|
||||
{ set_init_label ($1); }
|
||||
initelt
|
||||
| '.' identifier '='
|
||||
{ set_init_label ($2); }
|
||||
initelt
|
||||
;
|
||||
|
||||
nested_function:
|
||||
@ -1398,6 +1416,13 @@ parm_declarator:
|
||||
/* | parm_declarator '(' error ')' %prec '.'
|
||||
{ $$ = build_nt (CALL_EXPR, $1, NULL_TREE, NULL_TREE);
|
||||
poplevel (0, 0, 0); } */
|
||||
ifc
|
||||
| parm_declarator '[' '*' ']' %prec '.'
|
||||
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
|
||||
if (! flag_isoc9x)
|
||||
error ("`[*]' in parameter declaration only allowed in ISO C 9x");
|
||||
}
|
||||
end ifc
|
||||
| parm_declarator '[' expr ']' %prec '.'
|
||||
{ $$ = build_nt (ARRAY_REF, $1, $3); }
|
||||
| parm_declarator '[' ']' %prec '.'
|
||||
@ -1427,6 +1452,13 @@ notype_declarator:
|
||||
{ $$ = $2; }
|
||||
| '*' type_quals notype_declarator %prec UNARY
|
||||
{ $$ = make_pointer_declarator ($2, $3); }
|
||||
ifc
|
||||
| notype_declarator '[' '*' ']' %prec '.'
|
||||
{ $$ = build_nt (ARRAY_REF, $1, NULL_TREE);
|
||||
if (! flag_isoc9x)
|
||||
error ("`[*]' in parameter declaration only allowed in ISO C 9x");
|
||||
}
|
||||
end ifc
|
||||
| notype_declarator '[' expr ']' %prec '.'
|
||||
{ $$ = build_nt (ARRAY_REF, $1, $3); }
|
||||
| notype_declarator '[' ']' %prec '.'
|
||||
@ -1509,7 +1541,8 @@ maybecomma:
|
||||
maybecomma_warn:
|
||||
/* empty */
|
||||
| ','
|
||||
{ if (pedantic) pedwarn ("comma at end of enumerator list"); }
|
||||
{ if (pedantic && ! flag_isoc9x)
|
||||
pedwarn ("comma at end of enumerator list"); }
|
||||
;
|
||||
|
||||
component_decl_list:
|
||||
@ -1676,6 +1709,8 @@ absdcl1: /* a nonempty absolute declarator */
|
||||
{ $$ = build_nt (ARRAY_REF, NULL_TREE, NULL_TREE); }
|
||||
/* ??? It appears we have to support attributes here, however
|
||||
using prefix_attributes is wrong. */
|
||||
| attributes setattrs absdcl1
|
||||
{ $$ = $3; }
|
||||
;
|
||||
|
||||
/* at least one statement, the first of which parses without error. */
|
||||
@ -2191,12 +2226,15 @@ label: CASE expr_no_commas ':'
|
||||
error_with_decl (duplicate, "this is the first default label");
|
||||
}
|
||||
position_after_white_space (); }
|
||||
| identifier ':'
|
||||
| identifier ':' maybe_attribute
|
||||
{ tree label = define_label (input_filename, lineno, $1);
|
||||
stmt_count++;
|
||||
emit_nop ();
|
||||
if (label)
|
||||
expand_label (label);
|
||||
{
|
||||
expand_label (label);
|
||||
decl_attributes (label, $3, NULL_TREE);
|
||||
}
|
||||
position_after_white_space (); }
|
||||
;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
|
||||
Copyright (C) 1992, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -29,147 +29,464 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "flags.h"
|
||||
#include "toplev.h"
|
||||
|
||||
#ifdef HANDLE_SYSV_PRAGMA
|
||||
#ifdef HANDLE_GENERIC_PRAGMAS
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
/* When structure field packing is in effect, this variable is the
|
||||
number of bits to use as the maximum alignment. When packing is not
|
||||
in effect, this is zero. */
|
||||
|
||||
extern int maximum_field_alignment;
|
||||
#endif
|
||||
|
||||
/* File used for outputting assembler code. */
|
||||
extern FILE *asm_out_file;
|
||||
|
||||
/* Handle one token of a pragma directive. TOKEN is the
|
||||
current token, and STRING is its printable form. */
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
typedef struct align_stack
|
||||
{
|
||||
int alignment;
|
||||
unsigned int num_pushes;
|
||||
tree id;
|
||||
struct align_stack * prev;
|
||||
} align_stack;
|
||||
|
||||
static struct align_stack * alignment_stack = NULL;
|
||||
|
||||
static int push_alignment PROTO((int, tree));
|
||||
static int pop_alignment PROTO((tree));
|
||||
|
||||
/* Push an alignment value onto the stack. */
|
||||
static int
|
||||
push_alignment (alignment, id)
|
||||
int alignment;
|
||||
tree id;
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
break;
|
||||
default:
|
||||
warning ("\
|
||||
Alignment must be a small power of two, not %d, in #pragma pack",
|
||||
alignment);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alignment_stack == NULL
|
||||
|| alignment_stack->alignment != alignment
|
||||
|| id != NULL_TREE)
|
||||
{
|
||||
align_stack * entry;
|
||||
|
||||
entry = (align_stack *) xmalloc (sizeof (* entry));
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
warning ("Out of memory pushing #pragma pack");
|
||||
return 0;
|
||||
}
|
||||
|
||||
entry->alignment = alignment;
|
||||
entry->num_pushes = 1;
|
||||
entry->id = id;
|
||||
entry->prev = alignment_stack;
|
||||
|
||||
alignment_stack = entry;
|
||||
|
||||
maximum_field_alignment = alignment * 8;
|
||||
}
|
||||
else
|
||||
alignment_stack->num_pushes ++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Undo a push of an alignment onto the stack. */
|
||||
static int
|
||||
pop_alignment (id)
|
||||
tree id;
|
||||
{
|
||||
align_stack * entry;
|
||||
|
||||
if (alignment_stack == NULL)
|
||||
{
|
||||
warning ("\
|
||||
#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we got an identifier, strip away everything above the target
|
||||
entry so that the next step will restore the state just below it. */
|
||||
if (id)
|
||||
{
|
||||
for (entry = alignment_stack; entry; entry = entry->prev)
|
||||
if (entry->id == id)
|
||||
{
|
||||
entry->num_pushes = 1;
|
||||
alignment_stack = entry;
|
||||
break;
|
||||
}
|
||||
if (entry == NULL)
|
||||
warning ("\
|
||||
#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
|
||||
, IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
|
||||
}
|
||||
|
||||
if (-- alignment_stack->num_pushes == 0)
|
||||
{
|
||||
entry = alignment_stack->prev;
|
||||
|
||||
if (entry == NULL)
|
||||
maximum_field_alignment = 0;
|
||||
else
|
||||
maximum_field_alignment = entry->alignment * 8;
|
||||
|
||||
free (alignment_stack);
|
||||
|
||||
alignment_stack = entry;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generate 'packed' and 'aligned' attributes for decls whilst a
|
||||
#pragma pack(push... is in effect. */
|
||||
void
|
||||
insert_pack_attributes (node, attributes, prefix)
|
||||
tree node;
|
||||
tree * attributes;
|
||||
tree * prefix;
|
||||
{
|
||||
tree a;
|
||||
int field_alignment;
|
||||
|
||||
/* If we are not packing, then there is nothing to do. */
|
||||
if (maximum_field_alignment == 0
|
||||
|| alignment_stack == NULL)
|
||||
return;
|
||||
|
||||
/* We are only interested in fields. */
|
||||
if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
|
||||
|| TREE_CODE (node) != FIELD_DECL)
|
||||
return;
|
||||
|
||||
field_alignment = TYPE_ALIGN (TREE_TYPE (node));
|
||||
if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
|
||||
field_alignment = maximum_field_alignment;
|
||||
|
||||
/* Add a 'packed' attribute. */
|
||||
* attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
|
||||
|
||||
/* If the alignment is > 8 then add an alignment attribute as well. */
|
||||
if (field_alignment > 8)
|
||||
{
|
||||
/* If the aligned attribute is already present then do not override it. */
|
||||
for (a = * attributes; a; a = TREE_CHAIN (a))
|
||||
{
|
||||
tree name = TREE_PURPOSE (a);
|
||||
if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (a == NULL)
|
||||
for (a = * prefix; a; a = TREE_CHAIN (a))
|
||||
{
|
||||
tree name = TREE_PURPOSE (a);
|
||||
if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (a == NULL)
|
||||
{
|
||||
* attributes = tree_cons
|
||||
(get_identifier ("aligned"),
|
||||
tree_cons (NULL,
|
||||
build_int_2 (field_alignment / 8, 0),
|
||||
NULL),
|
||||
* attributes);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
/* Handle one token of a pragma directive. TOKEN is the current token, and
|
||||
STRING is its printable form. Some front ends do not support generating
|
||||
tokens, and will only pass in a STRING. Also some front ends will reuse
|
||||
the buffer containing STRING, so it must be copied to a local buffer if
|
||||
it needs to be preserved.
|
||||
|
||||
If STRING is non-NULL, then the return value will be ignored, and there
|
||||
will be futher calls to handle_pragma_token() in order to handle the rest of
|
||||
the line containing the #pragma directive. If STRING is NULL, the entire
|
||||
line has now been presented to handle_pragma_token() and the return value
|
||||
should be zero if the pragma flawed in some way, or if the pragma was not
|
||||
recognised, and non-zero if it was successfully handled. */
|
||||
|
||||
int
|
||||
handle_pragma_token (string, token)
|
||||
char *string;
|
||||
const char * string;
|
||||
tree token;
|
||||
{
|
||||
static enum pragma_state state = ps_start, type;
|
||||
static char *name;
|
||||
static char *value;
|
||||
static enum pragma_state state = ps_start;
|
||||
static enum pragma_state type;
|
||||
static char * name;
|
||||
static char * value;
|
||||
static int align;
|
||||
static tree id;
|
||||
|
||||
if (string == 0)
|
||||
/* If we have reached the end of the #pragma directive then
|
||||
determine what value we should return. */
|
||||
|
||||
if (string == NULL)
|
||||
{
|
||||
if (type == ps_pack)
|
||||
int ret_val = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case ps_done:
|
||||
/* The pragma was not recognised. */
|
||||
break;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
case ps_pack:
|
||||
if (state == ps_right)
|
||||
maximum_field_alignment = align * 8;
|
||||
{
|
||||
maximum_field_alignment = align * 8;
|
||||
ret_val = 1;
|
||||
}
|
||||
else
|
||||
warning ("malformed `#pragma pack'");
|
||||
}
|
||||
else if (type == ps_weak)
|
||||
{
|
||||
break;
|
||||
#endif /* HANDLE_PRAGMA_PACK */
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
case ps_push:
|
||||
if (state == ps_right)
|
||||
ret_val = push_alignment (align, id);
|
||||
else
|
||||
warning ("malformed '#pragma pack(push[,id],<n>)'");
|
||||
break;
|
||||
|
||||
case ps_pop:
|
||||
if (state == ps_right)
|
||||
ret_val = pop_alignment (id);
|
||||
else
|
||||
warning ("malformed '#pragma pack(pop[,id])'");
|
||||
break;
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
case ps_weak:
|
||||
if (HANDLE_PRAGMA_WEAK)
|
||||
handle_pragma_weak (state, name, value);
|
||||
|
||||
{
|
||||
if (state == ps_name)
|
||||
ret_val = add_weak (name, NULL);
|
||||
else if (state == ps_value)
|
||||
ret_val = add_weak (name, value);
|
||||
else
|
||||
warning ("malformed `#pragma weak'");
|
||||
}
|
||||
else
|
||||
ret_val = 1; /* Ignore the pragma. */
|
||||
break;
|
||||
#endif /* HANDLE_PRAGMA_WEAK */
|
||||
}
|
||||
|
||||
type = state = ps_start;
|
||||
return;
|
||||
id = NULL_TREE;
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/* If we have been given a token, but it is not an identifier,
|
||||
or a small constant, then something has gone wrong. */
|
||||
if (token)
|
||||
{
|
||||
switch (TREE_CODE (token))
|
||||
{
|
||||
case IDENTIFIER_NODE:
|
||||
break;
|
||||
|
||||
case INTEGER_CST:
|
||||
if (TREE_INT_CST_HIGH (token) != 0)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case ps_start:
|
||||
if (token && TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
type = state = ps_done;
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
if (strcmp (string, "pack") == 0)
|
||||
type = state = ps_pack;
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
if (strcmp (string, "weak") == 0)
|
||||
type = state = ps_weak;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
case ps_weak:
|
||||
name = permalloc (strlen (string) + 1);
|
||||
if (name == NULL)
|
||||
{
|
||||
if (strcmp (IDENTIFIER_POINTER (token), "pack") == 0)
|
||||
type = state = ps_pack;
|
||||
else if (strcmp (IDENTIFIER_POINTER (token), "weak") == 0)
|
||||
type = state = ps_weak;
|
||||
else
|
||||
{
|
||||
type = state = ps_done;
|
||||
|
||||
/* Issue a warning message if we have been asked to do so.
|
||||
Ignoring unknown pragmas in system header file unless
|
||||
an explcit -Wunknown-pragmas has been given. */
|
||||
if (warn_unknown_pragmas > 1
|
||||
|| (warn_unknown_pragmas && ! in_system_header))
|
||||
warning ("ignoring pragma: %s", string);
|
||||
}
|
||||
warning ("Out of memory parsing #pragma weak");
|
||||
state = ps_bad;
|
||||
}
|
||||
else
|
||||
type = state = ps_done;
|
||||
break;
|
||||
|
||||
case ps_weak:
|
||||
if (token && TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
{
|
||||
name = IDENTIFIER_POINTER (token);
|
||||
strcpy (name, string);
|
||||
state = ps_name;
|
||||
}
|
||||
else
|
||||
state = ps_bad;
|
||||
break;
|
||||
|
||||
|
||||
case ps_name:
|
||||
state = (strcmp (string, "=") ? ps_bad : ps_equals);
|
||||
break;
|
||||
|
||||
case ps_equals:
|
||||
if (token && TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
value = permalloc (strlen (string) + 1);
|
||||
if (value == NULL)
|
||||
{
|
||||
value = IDENTIFIER_POINTER (token);
|
||||
state = ps_value;
|
||||
warning ("Out of memory parsing #pragma weak");
|
||||
state = ps_bad;
|
||||
}
|
||||
else
|
||||
state = ps_bad;
|
||||
{
|
||||
strcpy (value, string);
|
||||
state = ps_value;
|
||||
}
|
||||
break;
|
||||
|
||||
case ps_value:
|
||||
state = ps_bad;
|
||||
break;
|
||||
|
||||
#endif /* HANDLE_PRAGMA_WEAK */
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
case ps_pack:
|
||||
if (strcmp (string, "(") == 0)
|
||||
state = ps_left;
|
||||
else
|
||||
state = ps_bad;
|
||||
state = (strcmp (string, "(") ? ps_bad : ps_left);
|
||||
break;
|
||||
|
||||
case ps_left:
|
||||
if (token && TREE_CODE (token) == INTEGER_CST
|
||||
&& TREE_INT_CST_HIGH (token) == 0)
|
||||
switch (TREE_INT_CST_LOW (token))
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
align = TREE_INT_CST_LOW (token);
|
||||
state = ps_align;
|
||||
break;
|
||||
|
||||
default:
|
||||
state = ps_bad;
|
||||
}
|
||||
else if (! token && strcmp (string, ")") == 0)
|
||||
if (token == NULL_TREE)
|
||||
{
|
||||
align = 0;
|
||||
state = ps_right;
|
||||
/* #pragma pack () resets packing rules to their
|
||||
defaults. */
|
||||
if (strcmp (string, ")") == 0)
|
||||
{
|
||||
align = 0;
|
||||
state = ps_right;
|
||||
}
|
||||
else
|
||||
state = ps_bad;
|
||||
}
|
||||
else if (TREE_CODE (token) == INTEGER_CST)
|
||||
goto handle_align;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
else if (TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
{
|
||||
if (strcmp (string, "push") == 0)
|
||||
type = state = ps_push;
|
||||
else if (strcmp (string, "pop") == 0)
|
||||
type = state = ps_pop;
|
||||
else
|
||||
state = ps_bad;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
state = ps_bad;
|
||||
break;
|
||||
|
||||
handle_align:
|
||||
align = TREE_INT_CST_LOW (token);
|
||||
switch (align)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
case 16:
|
||||
state = ps_align;
|
||||
break;
|
||||
|
||||
default:
|
||||
state = ps_bad;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case ps_align:
|
||||
if (strcmp (string, ")") == 0)
|
||||
state = ps_right;
|
||||
else
|
||||
state = ps_bad;
|
||||
state = (strcmp (string, ")") ? ps_bad : ps_right);
|
||||
break;
|
||||
|
||||
case ps_right:
|
||||
state = ps_bad;
|
||||
break;
|
||||
#endif /* HANDLE_PRAGMA_PACK */
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
case ps_push:
|
||||
state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
|
||||
break;
|
||||
|
||||
case ps_pushid:
|
||||
state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
|
||||
break;
|
||||
|
||||
case ps_pushcomma:
|
||||
if (token && TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
{
|
||||
id = token;
|
||||
state = ps_pushid;
|
||||
break;
|
||||
}
|
||||
|
||||
/* else fall through */
|
||||
case ps_pushcomma2:
|
||||
if (token && TREE_CODE (token) == INTEGER_CST)
|
||||
goto handle_align;
|
||||
else
|
||||
state = ps_bad;
|
||||
break;
|
||||
|
||||
case ps_pop:
|
||||
if (strcmp (string, ",") == 0)
|
||||
state = ps_popcomma;
|
||||
else
|
||||
state = (strcmp (string, ")") ? ps_bad : ps_right);
|
||||
break;
|
||||
|
||||
case ps_popcomma:
|
||||
if (token && TREE_CODE (token) == IDENTIFIER_NODE)
|
||||
{
|
||||
id = token;
|
||||
state = ps_align;
|
||||
}
|
||||
else
|
||||
state = ps_bad;
|
||||
break;
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
case ps_bad:
|
||||
case ps_done:
|
||||
break;
|
||||
@ -177,5 +494,7 @@ handle_pragma_token (string, token)
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* HANDLE_SYSV_PRAGMA */
|
||||
#endif /* HANDLE_GENERIC_PRAGMAS */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Pragma related interfaces.
|
||||
Copyright (C) 1995 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -18,29 +18,84 @@ 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. */
|
||||
|
||||
#ifndef _C_PRAGMA_H
|
||||
#define _C_PRAGMA_H
|
||||
|
||||
#ifdef HANDLE_SYSV_PRAGMA
|
||||
/* Support #pragma weak iff ASM_WEAKEN_LABEL and ASM_OUTPUT_DEF are
|
||||
defined. */
|
||||
#if defined (ASM_WEAKEN_LABEL) && defined (ASM_OUTPUT_DEF)
|
||||
#define HANDLE_PRAGMA_WEAK SUPPORTS_WEAK
|
||||
#endif
|
||||
|
||||
/* We always support #pragma pack for SYSV pragmas. */
|
||||
#ifndef HANDLE_PRAGMA_PACK
|
||||
#define HANDLE_PRAGMA_PACK 1
|
||||
#endif
|
||||
#endif /* HANDLE_SYSV_PRAGMA */
|
||||
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
/* If we are supporting #pragma pack(push... then we automatically
|
||||
support #pragma pack(<n>) */
|
||||
#define HANDLE_PRAGMA_PACK 1
|
||||
#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \
|
||||
insert_pack_attributes (node, pattr, prefix_attr)
|
||||
extern void insert_pack_attributes PROTO((tree, tree *, tree *));
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
/* This structure contains any weak symbol declarations waiting to be emitted. */
|
||||
struct weak_syms
|
||||
{
|
||||
struct weak_syms * next;
|
||||
char * name;
|
||||
char * value;
|
||||
};
|
||||
|
||||
/* Declared in varasm.c */
|
||||
extern struct weak_syms * weak_decls;
|
||||
|
||||
extern int add_weak PROTO((char *, char *));
|
||||
#endif /* HANDLE_PRAGMA_WEAK */
|
||||
|
||||
|
||||
#if defined HANDLE_PRAGMA_PACK || defined HANDLE_PRAGMA_WEAK
|
||||
/* Define HANDLE_GENERIC_PRAGMAS if any kind of front-end pragma
|
||||
parsing is to be done. The code in GCC's generic C source files
|
||||
will only look for the definition of this constant. They will
|
||||
ignore definitions of HANDLE_PRAGMA_PACK and so on. */
|
||||
#define HANDLE_GENERIC_PRAGMAS 1
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HANDLE_GENERIC_PRAGMAS
|
||||
enum pragma_state
|
||||
{
|
||||
ps_start,
|
||||
ps_done,
|
||||
ps_bad,
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
ps_weak,
|
||||
ps_name,
|
||||
ps_equals,
|
||||
ps_value,
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
ps_pack,
|
||||
ps_left,
|
||||
ps_align,
|
||||
ps_right
|
||||
ps_right,
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
ps_push, ps_pushcomma, ps_pushid, ps_pushcomma2,
|
||||
ps_pop, ps_popcomma,
|
||||
#endif
|
||||
ps_bad
|
||||
};
|
||||
|
||||
/* Output asm to handle ``#pragma weak'' */
|
||||
extern void handle_pragma_weak PROTO((enum pragma_state, char *, char *));
|
||||
|
||||
/* Handle a C style pragma */
|
||||
extern void handle_pragma_token PROTO((char *, tree));
|
||||
extern int handle_pragma_token PROTO((const char *, tree));
|
||||
|
||||
#endif /* HANDLE_GENERIC_PRAGMAS */
|
||||
#endif /* _C_PRAGMA_H */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for C parsing and type checking.
|
||||
Copyright (C) 1987, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
|
||||
Copyright (C) 1987, 93, 94, 95, 97, 98, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -80,6 +80,22 @@ extern int pedantic;
|
||||
nonzero if the definition of the type has already started. */
|
||||
#define C_TYPE_BEING_DEFINED(type) TYPE_LANG_FLAG_0 (type)
|
||||
|
||||
/* C types are partitioned into three subsets: object, function, and
|
||||
incomplete types. */
|
||||
#define C_TYPE_OBJECT_P(type) \
|
||||
(TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type))
|
||||
|
||||
#define C_TYPE_FUNCTION_P(type) \
|
||||
(TREE_CODE (type) == FUNCTION_TYPE)
|
||||
|
||||
#define C_TYPE_INCOMPLETE_P(type) \
|
||||
(TREE_CODE (type) != FUNCTION_TYPE && TYPE_SIZE (type) == 0)
|
||||
|
||||
/* For convenience we define a single macro to identify the class of
|
||||
object or incomplete types. */
|
||||
#define C_TYPE_OBJECT_OR_INCOMPLETE_P(type) \
|
||||
(!C_TYPE_FUNCTION_P (type))
|
||||
|
||||
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
|
||||
struct lang_type
|
||||
{
|
||||
@ -154,7 +170,7 @@ extern int maybe_objc_comptypes PROTO((tree, tree, int));
|
||||
extern tree maybe_building_objc_message_expr PROTO((void));
|
||||
extern tree maybe_objc_method_name PROTO((tree));
|
||||
extern int recognize_objc_keyword PROTO((void));
|
||||
extern tree build_objc_string PROTO((int, char *));
|
||||
extern tree build_objc_string PROTO((int, const char *));
|
||||
|
||||
/* in c-aux-info.c */
|
||||
extern void gen_aux_info_record PROTO((tree, int, int, int));
|
||||
@ -165,6 +181,7 @@ extern void decl_attributes PROTO((tree, tree, tree));
|
||||
extern void init_function_format_info PROTO((void));
|
||||
extern void check_function_format PROTO((tree, tree, tree));
|
||||
extern int c_get_alias_set PROTO((tree));
|
||||
extern void c_apply_type_quals_to_decl PROTO((int, tree));
|
||||
/* Print an error message for invalid operands to arith operation CODE.
|
||||
NOP_EXPR is used as a special case (see truthvalue_conversion). */
|
||||
extern void binary_op_error PROTO((enum tree_code));
|
||||
@ -213,7 +230,9 @@ extern tree double_ftype_double;
|
||||
extern tree double_ftype_double_double;
|
||||
extern tree double_type_node;
|
||||
extern tree float_type_node;
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
extern tree intTI_type_node;
|
||||
#endif
|
||||
extern tree intDI_type_node;
|
||||
extern tree intHI_type_node;
|
||||
extern tree intQI_type_node;
|
||||
@ -243,7 +262,9 @@ extern tree signed_wchar_type_node;
|
||||
extern tree string_ftype_ptr_ptr;
|
||||
extern tree string_type_node;
|
||||
extern tree unsigned_char_type_node;
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
extern tree unsigned_intTI_type_node;
|
||||
#endif
|
||||
extern tree unsigned_intDI_type_node;
|
||||
extern tree unsigned_intHI_type_node;
|
||||
extern tree unsigned_intQI_type_node;
|
||||
@ -261,9 +282,13 @@ extern tree boolean_false_node;
|
||||
|
||||
extern tree build_enumerator PROTO((tree, tree));
|
||||
/* Declare a predefined function. Return the declaration. */
|
||||
extern tree builtin_function PROTO((char *, tree, enum built_in_function function_, char *));
|
||||
extern tree builtin_function PROTO((const char *, tree, enum built_in_function function_, const char *));
|
||||
/* Add qualifiers to a type, in the fashion for C. */
|
||||
extern tree c_build_type_variant PROTO((tree, int, int));
|
||||
extern tree c_build_qualified_type PROTO((tree, int));
|
||||
#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))
|
||||
extern int c_decode_option PROTO((int, char **));
|
||||
extern void c_mark_varargs PROTO((void));
|
||||
extern tree check_identifier PROTO((tree, tree));
|
||||
@ -282,7 +307,7 @@ extern tree get_parm_info PROTO((int));
|
||||
extern tree getdecls PROTO((void));
|
||||
extern tree gettags PROTO((void));
|
||||
extern int global_bindings_p PROTO((void));
|
||||
extern tree grokfield PROTO((char *, int, tree, tree, tree));
|
||||
extern tree grokfield PROTO((const char *, int, tree, tree, tree));
|
||||
extern tree groktypename PROTO((tree));
|
||||
extern tree groktypename_in_parm_context PROTO((tree));
|
||||
extern tree implicitly_declare PROTO((tree));
|
||||
@ -340,7 +365,7 @@ extern tree c_alignof PROTO((tree));
|
||||
extern tree c_alignof_expr PROTO((tree));
|
||||
extern tree default_conversion PROTO((tree));
|
||||
extern tree build_component_ref PROTO((tree, tree));
|
||||
extern tree build_indirect_ref PROTO((tree, char *));
|
||||
extern tree build_indirect_ref PROTO((tree, const char *));
|
||||
extern tree build_array_ref PROTO((tree, tree));
|
||||
extern tree build_function_call PROTO((tree, tree));
|
||||
extern tree parser_build_binary_op PROTO((enum tree_code,
|
||||
@ -350,8 +375,8 @@ extern tree build_binary_op PROTO((enum tree_code,
|
||||
extern tree build_unary_op PROTO((enum tree_code,
|
||||
tree, int));
|
||||
extern int lvalue_p PROTO((tree));
|
||||
extern int lvalue_or_else PROTO((tree, char *));
|
||||
extern void readonly_warning PROTO((tree, char *));
|
||||
extern int lvalue_or_else PROTO((tree, const char *));
|
||||
extern void readonly_warning PROTO((tree, const char *));
|
||||
extern int mark_addressable PROTO((tree));
|
||||
extern tree build_conditional_expr PROTO((tree, tree, tree));
|
||||
extern tree build_compound_expr PROTO((tree));
|
||||
@ -360,10 +385,8 @@ extern tree build_modify_expr PROTO((tree, enum tree_code,
|
||||
tree));
|
||||
extern tree initializer_constant_valid_p PROTO((tree, tree));
|
||||
extern void store_init_value PROTO((tree, tree));
|
||||
extern void error_init PROTO((char *, char *,
|
||||
char *));
|
||||
extern void pedwarn_init PROTO((char *, char *,
|
||||
char *));
|
||||
extern void error_init PROTO((const char *));
|
||||
extern void pedwarn_init PROTO((const char *));
|
||||
extern void start_init PROTO((tree, tree, int));
|
||||
extern void finish_init PROTO((void));
|
||||
extern void really_start_incremental_init PROTO((tree));
|
||||
@ -418,10 +441,6 @@ extern int flag_no_asm;
|
||||
|
||||
extern int flag_hosted;
|
||||
|
||||
/* Nonzero means ignore `#ident' directives. */
|
||||
|
||||
extern int flag_no_ident;
|
||||
|
||||
/* Nonzero means warn about implicit declarations. */
|
||||
|
||||
extern int warn_implicit;
|
||||
@ -430,7 +449,7 @@ extern int warn_implicit;
|
||||
to get extra warnings from them. These warnings will be too numerous
|
||||
to be useful, except in thoroughly ANSIfied programs. */
|
||||
|
||||
extern int warn_write_strings;
|
||||
extern int flag_const_strings;
|
||||
|
||||
/* Nonzero means warn about sizeof (function) or addition/subtraction
|
||||
of function pointers. */
|
||||
@ -465,6 +484,10 @@ extern int warn_cast_qual;
|
||||
|
||||
extern int warn_bad_function_cast;
|
||||
|
||||
/* Warn about functions which might be candidates for attribute noreturn. */
|
||||
|
||||
extern int warn_missing_noreturn;
|
||||
|
||||
/* Warn about traditional constructs whose meanings changed in ANSI C. */
|
||||
|
||||
extern int warn_traditional;
|
||||
@ -489,6 +512,10 @@ extern int warn_main;
|
||||
|
||||
extern int flag_traditional;
|
||||
|
||||
/* Nonzero means use the ISO C9x dialect of C. */
|
||||
|
||||
extern int flag_isoc9x;
|
||||
|
||||
/* Nonzero means to allow single precision math even if we're generally
|
||||
being traditional. */
|
||||
extern int flag_allow_single_precision;
|
||||
@ -509,6 +536,10 @@ extern int warn_sign_compare;
|
||||
|
||||
extern int warn_multichar;
|
||||
|
||||
/* Warn about long long. */
|
||||
|
||||
extern int warn_long_long;
|
||||
|
||||
/* Nonzero means we are reading code that came from a system header file. */
|
||||
|
||||
extern int system_header_p;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Save and restore call-clobbered registers which are live across a call.
|
||||
Copyright (C) 1989, 1992, 94-95, 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1989, 1992, 94-95, 97, 98, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -39,6 +39,8 @@ Boston, MA 02111-1307, USA. */
|
||||
#define MIN_UNITS_PER_WORD UNITS_PER_WORD
|
||||
#endif
|
||||
|
||||
#define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD)
|
||||
|
||||
/* Modes for each hard register that we can save. The smallest mode is wide
|
||||
enough to save the entire contents of the register. When saving the
|
||||
register because it is live we first try to save in multi-register modes.
|
||||
@ -64,27 +66,31 @@ static enum insn_code
|
||||
static enum insn_code
|
||||
reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
|
||||
|
||||
/* Set of hard regs currently live (during scan of all insns). */
|
||||
|
||||
static HARD_REG_SET hard_regs_live;
|
||||
|
||||
/* Set of hard regs currently residing in save area (during insn scan). */
|
||||
|
||||
static HARD_REG_SET hard_regs_saved;
|
||||
|
||||
/* Set of hard regs which need to be restored before referenced. */
|
||||
|
||||
static HARD_REG_SET hard_regs_need_restore;
|
||||
|
||||
/* Number of registers currently in hard_regs_saved. */
|
||||
|
||||
int n_regs_saved;
|
||||
static int n_regs_saved;
|
||||
|
||||
static void set_reg_live PROTO((rtx, rtx));
|
||||
static void clear_reg_live PROTO((rtx));
|
||||
static void restore_referenced_regs PROTO((rtx, rtx, enum machine_mode));
|
||||
static int insert_save_restore PROTO((rtx, int, int,
|
||||
enum machine_mode, int));
|
||||
/* Computed by mark_referenced_regs, all regs referenced in a given
|
||||
insn. */
|
||||
static HARD_REG_SET referenced_regs;
|
||||
|
||||
/* Computed in mark_set_regs, holds all registers set by the current
|
||||
instruction. */
|
||||
static HARD_REG_SET this_insn_sets;
|
||||
|
||||
|
||||
static void mark_set_regs PROTO((rtx, rtx));
|
||||
static void mark_referenced_regs PROTO((rtx));
|
||||
static int insert_save PROTO((struct insn_chain *, int, int,
|
||||
HARD_REG_SET *));
|
||||
static int insert_restore PROTO((struct insn_chain *, int, int,
|
||||
int));
|
||||
static void insert_one_insn PROTO((struct insn_chain *, int,
|
||||
enum insn_code, rtx));
|
||||
|
||||
/* Initialize for caller-save.
|
||||
|
||||
@ -113,9 +119,9 @@ init_caller_save ()
|
||||
{
|
||||
if (call_used_regs[i] && ! call_fixed_regs[i])
|
||||
{
|
||||
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
|
||||
for (j = 1; j <= MOVE_MAX_WORDS; j++)
|
||||
{
|
||||
regno_save_mode[i][j] = choose_hard_reg_mode (i, j);
|
||||
regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j);
|
||||
if (regno_save_mode[i][j] == VOIDmode && j == 1)
|
||||
{
|
||||
call_fixed_regs[i] = 1;
|
||||
@ -170,7 +176,7 @@ init_caller_save ()
|
||||
start_sequence ();
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
|
||||
for (j = 1; j <= MOVE_MAX_WORDS; j++)
|
||||
if (regno_save_mode[i][j] != VOIDmode)
|
||||
{
|
||||
rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address);
|
||||
@ -186,13 +192,14 @@ init_caller_save ()
|
||||
|
||||
/* Now extract both insns and see if we can meet their
|
||||
constraints. */
|
||||
ok = (reg_save_code[i][j] != -1 && reg_restore_code[i][j] != -1);
|
||||
ok = (reg_save_code[i][j] != (enum insn_code)-1
|
||||
&& reg_restore_code[i][j] != (enum insn_code)-1);
|
||||
if (ok)
|
||||
{
|
||||
insn_extract (saveinsn);
|
||||
ok = constrain_operands (reg_save_code[i][j], 1);
|
||||
insn_extract (restinsn);
|
||||
ok &= constrain_operands (reg_restore_code[i][j], 1);
|
||||
extract_insn (saveinsn);
|
||||
ok = constrain_operands (1);
|
||||
extract_insn (restinsn);
|
||||
ok &= constrain_operands (1);
|
||||
}
|
||||
|
||||
if (! ok)
|
||||
@ -219,7 +226,7 @@ init_save_areas ()
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
|
||||
for (j = 1; j <= MOVE_MAX_WORDS; j++)
|
||||
regno_save_mem[i][j] = 0;
|
||||
}
|
||||
|
||||
@ -229,13 +236,6 @@ init_save_areas ()
|
||||
overestimate slightly (especially if some of these registers are later
|
||||
used as spill registers), but it should not be significant.
|
||||
|
||||
Then perform register elimination in the addresses of the save area
|
||||
locations; return 1 if all eliminated addresses are strictly valid.
|
||||
We assume that our caller has set up the elimination table to the
|
||||
worst (largest) possible offsets.
|
||||
|
||||
Set *PCHANGED to 1 if we had to allocate some memory for the save area.
|
||||
|
||||
Future work:
|
||||
|
||||
In the fallback case we should iterate backwards across all possible
|
||||
@ -248,14 +248,11 @@ init_save_areas ()
|
||||
machine independent since they might be saving non-consecutive
|
||||
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
|
||||
|
||||
int
|
||||
setup_save_areas (pchanged)
|
||||
int *pchanged;
|
||||
void
|
||||
setup_save_areas ()
|
||||
{
|
||||
int i, j, k;
|
||||
HARD_REG_SET hard_regs_used;
|
||||
int ok = 1;
|
||||
|
||||
|
||||
/* Allocate space in the save area for the largest multi-register
|
||||
pseudos first, then work backwards to single register
|
||||
@ -283,10 +280,9 @@ setup_save_areas (pchanged)
|
||||
in a manner which allows multi-register saves/restores to be done. */
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
for (j = MOVE_MAX / UNITS_PER_WORD; j > 0; j--)
|
||||
for (j = MOVE_MAX_WORDS; j > 0; j--)
|
||||
{
|
||||
int ok = 1;
|
||||
int do_save;
|
||||
int do_save = 1;
|
||||
|
||||
/* If no mode exists for this size, try another. Also break out
|
||||
if we have already saved this hard register. */
|
||||
@ -294,7 +290,6 @@ setup_save_areas (pchanged)
|
||||
continue;
|
||||
|
||||
/* See if any register in this group has been saved. */
|
||||
do_save = 1;
|
||||
for (k = 0; k < j; k++)
|
||||
if (regno_save_mem[i + k][1])
|
||||
{
|
||||
@ -305,207 +300,171 @@ setup_save_areas (pchanged)
|
||||
continue;
|
||||
|
||||
for (k = 0; k < j; k++)
|
||||
if (! TEST_HARD_REG_BIT (hard_regs_used, i + k))
|
||||
{
|
||||
int regno = i + k;
|
||||
ok &= (TEST_HARD_REG_BIT (hard_regs_used, regno) != 0);
|
||||
do_save = 0;
|
||||
break;
|
||||
}
|
||||
if (! do_save)
|
||||
continue;
|
||||
|
||||
/* We have found an acceptable mode to store in. */
|
||||
if (ok)
|
||||
regno_save_mem[i][j]
|
||||
= assign_stack_local (regno_save_mode[i][j],
|
||||
GET_MODE_SIZE (regno_save_mode[i][j]), 0);
|
||||
|
||||
/* Setup single word save area just in case... */
|
||||
for (k = 0; k < j; k++)
|
||||
{
|
||||
/* This should not depend on WORDS_BIG_ENDIAN.
|
||||
The order of words in regs is the same as in memory. */
|
||||
rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
|
||||
XEXP (regno_save_mem[i][j], 0));
|
||||
|
||||
regno_save_mem[i][j]
|
||||
= assign_stack_local (regno_save_mode[i][j],
|
||||
GET_MODE_SIZE (regno_save_mode[i][j]), 0);
|
||||
|
||||
/* Setup single word save area just in case... */
|
||||
for (k = 0; k < j; k++)
|
||||
{
|
||||
/* This should not depend on WORDS_BIG_ENDIAN.
|
||||
The order of words in regs is the same as in memory. */
|
||||
rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1],
|
||||
XEXP (regno_save_mem[i][j], 0));
|
||||
|
||||
regno_save_mem[i+k][1]
|
||||
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
|
||||
}
|
||||
*pchanged = 1;
|
||||
regno_save_mem[i+k][1]
|
||||
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
|
||||
if (regno_save_mem[i][j] != 0)
|
||||
ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]),
|
||||
XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0));
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Find the places where hard regs are live across calls and save them.
|
||||
|
||||
INSN_MODE is the mode to assign to any insns that we add. This is used
|
||||
by reload to determine whether or not reloads or register eliminations
|
||||
need be done on these insns. */
|
||||
|
||||
/* Find the places where hard regs are live across calls and save them. */
|
||||
void
|
||||
save_call_clobbered_regs (insn_mode)
|
||||
enum machine_mode insn_mode;
|
||||
save_call_clobbered_regs ()
|
||||
{
|
||||
rtx insn;
|
||||
int b;
|
||||
struct insn_chain *chain, *next;
|
||||
|
||||
for (b = 0; b < n_basic_blocks; b++)
|
||||
CLEAR_HARD_REG_SET (hard_regs_saved);
|
||||
n_regs_saved = 0;
|
||||
|
||||
for (chain = reload_insn_chain; chain != 0; chain = next)
|
||||
{
|
||||
regset regs_live = basic_block_live_at_start[b];
|
||||
rtx prev_block_last = PREV_INSN (basic_block_head[b]);
|
||||
int i, j;
|
||||
int regno;
|
||||
rtx insn = chain->insn;
|
||||
enum rtx_code code = GET_CODE (insn);
|
||||
|
||||
/* Compute hard regs live at start of block -- this is the
|
||||
real hard regs marked live, plus live pseudo regs that
|
||||
have been renumbered to hard regs. No registers have yet been
|
||||
saved because we restore all of them before the end of the basic
|
||||
block. */
|
||||
next = chain->next;
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (hard_regs_live, regs_live);
|
||||
CLEAR_HARD_REG_SET (hard_regs_saved);
|
||||
CLEAR_HARD_REG_SET (hard_regs_need_restore);
|
||||
n_regs_saved = 0;
|
||||
if (chain->is_caller_save_insn)
|
||||
abort ();
|
||||
|
||||
EXECUTE_IF_SET_IN_REG_SET (regs_live, 0, i,
|
||||
{
|
||||
if ((regno = reg_renumber[i]) >= 0)
|
||||
for (j = regno;
|
||||
j < regno + HARD_REGNO_NREGS (regno,
|
||||
PSEUDO_REGNO_MODE (i));
|
||||
j++)
|
||||
SET_HARD_REG_BIT (hard_regs_live, j);
|
||||
});
|
||||
|
||||
/* Now scan the insns in the block, keeping track of what hard
|
||||
regs are live as we go. When we see a call, save the live
|
||||
call-clobbered hard regs. */
|
||||
|
||||
for (insn = basic_block_head[b]; ; insn = NEXT_INSN (insn))
|
||||
if (GET_RTX_CLASS (code) == 'i')
|
||||
{
|
||||
RTX_CODE code = GET_CODE (insn);
|
||||
/* If some registers have been saved, see if INSN references
|
||||
any of them. We must restore them before the insn if so. */
|
||||
|
||||
if (GET_RTX_CLASS (code) == 'i')
|
||||
if (n_regs_saved)
|
||||
{
|
||||
rtx link;
|
||||
int regno;
|
||||
|
||||
/* If some registers have been saved, see if INSN references
|
||||
any of them. We must restore them before the insn if so. */
|
||||
|
||||
if (n_regs_saved)
|
||||
restore_referenced_regs (PATTERN (insn), insn, insn_mode);
|
||||
|
||||
/* NB: the normal procedure is to first enliven any
|
||||
registers set by insn, then deaden any registers that
|
||||
had their last use at insn. This is incorrect now,
|
||||
since multiple pseudos may have been mapped to the
|
||||
same hard reg, and the death notes are ambiguous. So
|
||||
it must be done in the other, safe, order. */
|
||||
|
||||
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
|
||||
if (REG_NOTE_KIND (link) == REG_DEAD)
|
||||
clear_reg_live (XEXP (link, 0));
|
||||
|
||||
/* When we reach a call, we need to save all registers that are
|
||||
live, call-used, not fixed, and not already saved. We must
|
||||
test at this point because registers that die in a CALL_INSN
|
||||
are not live across the call and likewise for registers that
|
||||
are born in the CALL_INSN.
|
||||
|
||||
If registers are filled with parameters for this function,
|
||||
and some of these are also being set by this function, then
|
||||
they will not appear to die (no REG_DEAD note for them),
|
||||
to check if in fact they do, collect the set registers in
|
||||
hard_regs_live first. */
|
||||
|
||||
if (code == CALL_INSN)
|
||||
{
|
||||
HARD_REG_SET this_call_sets;
|
||||
{
|
||||
HARD_REG_SET old_hard_regs_live;
|
||||
|
||||
/* Save the hard_regs_live information. */
|
||||
COPY_HARD_REG_SET (old_hard_regs_live, hard_regs_live);
|
||||
|
||||
/* Now calculate hard_regs_live for this CALL_INSN
|
||||
only. */
|
||||
CLEAR_HARD_REG_SET (hard_regs_live);
|
||||
note_stores (PATTERN (insn), set_reg_live);
|
||||
COPY_HARD_REG_SET (this_call_sets, hard_regs_live);
|
||||
|
||||
/* Restore the hard_regs_live information. */
|
||||
COPY_HARD_REG_SET (hard_regs_live, old_hard_regs_live);
|
||||
}
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (call_used_regs[regno] && ! call_fixed_regs[regno]
|
||||
&& TEST_HARD_REG_BIT (hard_regs_live, regno)
|
||||
/* It must not be set by this instruction. */
|
||||
&& ! TEST_HARD_REG_BIT (this_call_sets, regno)
|
||||
&& ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
|
||||
regno += insert_save_restore (insn, 1, regno,
|
||||
insn_mode, 0);
|
||||
|
||||
/* Put the information for this CALL_INSN on top of what
|
||||
we already had. */
|
||||
IOR_HARD_REG_SET (hard_regs_live, this_call_sets);
|
||||
COPY_HARD_REG_SET (hard_regs_need_restore, hard_regs_saved);
|
||||
|
||||
/* Must recompute n_regs_saved. */
|
||||
n_regs_saved = 0;
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
|
||||
n_regs_saved++;
|
||||
}
|
||||
if (code == JUMP_INSN)
|
||||
/* Restore all registers if this is a JUMP_INSN. */
|
||||
COPY_HARD_REG_SET (referenced_regs, hard_regs_saved);
|
||||
else
|
||||
{
|
||||
note_stores (PATTERN (insn), set_reg_live);
|
||||
#ifdef AUTO_INC_DEC
|
||||
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
|
||||
if (REG_NOTE_KIND (link) == REG_INC)
|
||||
set_reg_live (XEXP (link, 0), NULL_RTX);
|
||||
#endif
|
||||
CLEAR_HARD_REG_SET (referenced_regs);
|
||||
mark_referenced_regs (PATTERN (insn));
|
||||
AND_HARD_REG_SET (referenced_regs, hard_regs_saved);
|
||||
}
|
||||
|
||||
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
|
||||
if (REG_NOTE_KIND (link) == REG_UNUSED)
|
||||
clear_reg_live (XEXP (link, 0));
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (referenced_regs, regno))
|
||||
regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS);
|
||||
}
|
||||
|
||||
if (insn == basic_block_end[b])
|
||||
break;
|
||||
if (code == CALL_INSN)
|
||||
{
|
||||
rtx x;
|
||||
int regno, nregs;
|
||||
HARD_REG_SET hard_regs_to_save;
|
||||
|
||||
/* Use the register life information in CHAIN to compute which
|
||||
regs are live before the call. */
|
||||
REG_SET_TO_HARD_REG_SET (hard_regs_to_save, chain->live_before);
|
||||
compute_use_by_pseudos (&hard_regs_to_save, chain->live_before);
|
||||
|
||||
/* Record all registers set in this call insn. These don't need
|
||||
to be saved. */
|
||||
CLEAR_HARD_REG_SET (this_insn_sets);
|
||||
note_stores (PATTERN (insn), mark_set_regs);
|
||||
|
||||
/* Compute which hard regs must be saved before this call. */
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
|
||||
AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
|
||||
|
||||
/* Registers used for function parameters need not be saved. */
|
||||
for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0;
|
||||
x = XEXP (x, 1))
|
||||
{
|
||||
rtx y;
|
||||
|
||||
if (GET_CODE (XEXP (x, 0)) != USE)
|
||||
continue;
|
||||
y = XEXP (XEXP (x, 0), 0);
|
||||
if (GET_CODE (y) != REG)
|
||||
abort ();
|
||||
regno = REGNO (y);
|
||||
if (REGNO (y) >= FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
|
||||
while (nregs-- > 0)
|
||||
CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
|
||||
}
|
||||
|
||||
/* Neither do registers for which we find a death note. */
|
||||
for (x = REG_NOTES (insn); x != 0; x = XEXP (x, 1))
|
||||
{
|
||||
rtx y = XEXP (x, 0);
|
||||
|
||||
if (REG_NOTE_KIND (x) != REG_DEAD)
|
||||
continue;
|
||||
if (GET_CODE (y) != REG)
|
||||
abort ();
|
||||
regno = REGNO (y);
|
||||
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
regno = reg_renumber[regno];
|
||||
if (regno < 0)
|
||||
continue;
|
||||
nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
|
||||
while (nregs-- > 0)
|
||||
CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
|
||||
}
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
|
||||
regno += insert_save (chain, 1, regno, &hard_regs_to_save);
|
||||
|
||||
/* Must recompute n_regs_saved. */
|
||||
n_regs_saved = 0;
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
|
||||
n_regs_saved++;
|
||||
}
|
||||
}
|
||||
|
||||
/* At the end of the basic block, we must restore any registers that
|
||||
remain saved. If the last insn in the block is a JUMP_INSN, put
|
||||
the restore before the insn, otherwise, put it after the insn. */
|
||||
if (chain->next == 0 || chain->next->block > chain->block)
|
||||
{
|
||||
int regno;
|
||||
/* At the end of the basic block, we must restore any registers that
|
||||
remain saved. If the last insn in the block is a JUMP_INSN, put
|
||||
the restore before the insn, otherwise, put it after the insn. */
|
||||
|
||||
if (n_regs_saved)
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
|
||||
regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
|
||||
? insn : NEXT_INSN (insn)), 0,
|
||||
regno, insn_mode, MOVE_MAX / UNITS_PER_WORD);
|
||||
|
||||
/* If we added any insns at the start of the block, update the start
|
||||
of the block to point at those insns. */
|
||||
basic_block_head[b] = NEXT_INSN (prev_block_last);
|
||||
}
|
||||
if (n_regs_saved)
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
|
||||
regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN,
|
||||
regno, MOVE_MAX_WORDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here from note_stores when an insn stores a value in a register.
|
||||
Set the proper bit or bits in hard_regs_live. All pseudos that have
|
||||
Set the proper bit or bits in this_insn_sets. All pseudos that have
|
||||
been assigned hard regs have had their register number changed already,
|
||||
so we can ignore pseudos. */
|
||||
|
||||
static void
|
||||
set_reg_live (reg, setter)
|
||||
mark_set_regs (reg, setter)
|
||||
rtx reg;
|
||||
rtx setter ATTRIBUTE_UNUSED;
|
||||
{
|
||||
@ -526,105 +485,71 @@ set_reg_live (reg, setter)
|
||||
endregno = regno + HARD_REGNO_NREGS (regno, mode);
|
||||
|
||||
for (i = regno; i < endregno; i++)
|
||||
{
|
||||
SET_HARD_REG_BIT (hard_regs_live, i);
|
||||
CLEAR_HARD_REG_BIT (hard_regs_saved, i);
|
||||
CLEAR_HARD_REG_BIT (hard_regs_need_restore, i);
|
||||
}
|
||||
SET_HARD_REG_BIT (this_insn_sets, i);
|
||||
}
|
||||
|
||||
/* Here when a REG_DEAD note records the last use of a reg. Clear
|
||||
the appropriate bit or bits in hard_regs_live. Again we can ignore
|
||||
pseudos. */
|
||||
|
||||
/* Walk X and record all referenced registers in REFERENCED_REGS. */
|
||||
static void
|
||||
clear_reg_live (reg)
|
||||
rtx reg;
|
||||
{
|
||||
register int regno, endregno, i;
|
||||
|
||||
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
||||
return;
|
||||
|
||||
regno = REGNO (reg);
|
||||
endregno= regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
|
||||
|
||||
for (i = regno; i < endregno; i++)
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (hard_regs_live, i);
|
||||
CLEAR_HARD_REG_BIT (hard_regs_need_restore, i);
|
||||
CLEAR_HARD_REG_BIT (hard_regs_saved, i);
|
||||
}
|
||||
}
|
||||
|
||||
/* If any register currently residing in the save area is referenced in X,
|
||||
which is part of INSN, emit code to restore the register in front of INSN.
|
||||
INSN_MODE is the mode to assign to any insns that we add. */
|
||||
|
||||
static void
|
||||
restore_referenced_regs (x, insn, insn_mode)
|
||||
mark_referenced_regs (x)
|
||||
rtx x;
|
||||
rtx insn;
|
||||
enum machine_mode insn_mode;
|
||||
{
|
||||
enum rtx_code code = GET_CODE (x);
|
||||
char *fmt;
|
||||
int i, j;
|
||||
|
||||
if (code == CLOBBER)
|
||||
return;
|
||||
if (code == SET)
|
||||
mark_referenced_regs (SET_SRC (x));
|
||||
if (code == SET || code == CLOBBER)
|
||||
{
|
||||
x = SET_DEST (x);
|
||||
code = GET_CODE (x);
|
||||
if (code == REG || code == PC || code == CC0
|
||||
|| (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG))
|
||||
return;
|
||||
}
|
||||
if (code == MEM || code == SUBREG)
|
||||
{
|
||||
x = XEXP (x, 0);
|
||||
code = GET_CODE (x);
|
||||
}
|
||||
|
||||
if (code == REG)
|
||||
{
|
||||
int regno = REGNO (x);
|
||||
int hardregno = (regno < FIRST_PSEUDO_REGISTER ? regno
|
||||
: reg_renumber[regno]);
|
||||
|
||||
/* If this is a pseudo, scan its memory location, since it might
|
||||
involve the use of another register, which might be saved. */
|
||||
|
||||
if (regno >= FIRST_PSEUDO_REGISTER
|
||||
&& reg_equiv_mem[regno] != 0)
|
||||
restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
|
||||
insn, insn_mode);
|
||||
else if (regno >= FIRST_PSEUDO_REGISTER
|
||||
&& reg_equiv_address[regno] != 0)
|
||||
restore_referenced_regs (reg_equiv_address[regno],
|
||||
insn, insn_mode);
|
||||
|
||||
/* Otherwise if this is a hard register, restore any piece of it that
|
||||
is currently saved. */
|
||||
|
||||
else if (regno < FIRST_PSEUDO_REGISTER)
|
||||
if (hardregno >= 0)
|
||||
{
|
||||
int numregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
|
||||
/* Save at most SAVEREGS at a time. This can not be larger than
|
||||
MOVE_MAX, because that causes insert_save_restore to fail. */
|
||||
int saveregs = MIN (numregs, MOVE_MAX / UNITS_PER_WORD);
|
||||
int endregno = regno + numregs;
|
||||
|
||||
for (i = regno; i < endregno; i++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
|
||||
i += insert_save_restore (insn, 0, i, insn_mode, saveregs);
|
||||
int nregs = HARD_REGNO_NREGS (hardregno, GET_MODE (x));
|
||||
while (nregs-- > 0)
|
||||
SET_HARD_REG_BIT (referenced_regs, hardregno + nregs);
|
||||
}
|
||||
|
||||
/* If this is a pseudo that did not get a hard register, scan its
|
||||
memory location, since it might involve the use of another
|
||||
register, which might be saved. */
|
||||
else if (reg_equiv_mem[regno] != 0)
|
||||
mark_referenced_regs (XEXP (reg_equiv_mem[regno], 0));
|
||||
else if (reg_equiv_address[regno] != 0)
|
||||
mark_referenced_regs (reg_equiv_address[regno]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
fmt = GET_RTX_FORMAT (code);
|
||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||
{
|
||||
if (fmt[i] == 'e')
|
||||
restore_referenced_regs (XEXP (x, i), insn, insn_mode);
|
||||
mark_referenced_regs (XEXP (x, i));
|
||||
else if (fmt[i] == 'E')
|
||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
||||
restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode);
|
||||
mark_referenced_regs (XVECEXP (x, i, j));
|
||||
}
|
||||
}
|
||||
|
||||
/* Insert a sequence of insns to save or restore, SAVE_P says which,
|
||||
REGNO. Place these insns in front of INSN. INSN_MODE is the mode
|
||||
to assign to these insns. MAXRESTORE is the maximum number of registers
|
||||
which should be restored during this call (when SAVE_P == 0). It should
|
||||
never be less than 1 since we only work with entire registers.
|
||||
/* Insert a sequence of insns to restore. Place these insns in front of
|
||||
CHAIN if BEFORE_P is nonzero, behind the insn otherwise. MAXRESTORE is
|
||||
the maximum number of registers which should be restored during this call.
|
||||
It should never be less than 1 since we only work with entire registers.
|
||||
|
||||
Note that we have verified in init_caller_save that we can do this
|
||||
with a simple SET, so use it. Set INSN_CODE to what we save there
|
||||
@ -635,13 +560,13 @@ restore_referenced_regs (x, insn, insn_mode)
|
||||
Return the extra number of registers saved. */
|
||||
|
||||
static int
|
||||
insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
|
||||
rtx insn;
|
||||
int save_p;
|
||||
insert_restore (chain, before_p, regno, maxrestore)
|
||||
struct insn_chain *chain;
|
||||
int before_p;
|
||||
int regno;
|
||||
enum machine_mode insn_mode;
|
||||
int maxrestore;
|
||||
{
|
||||
int i;
|
||||
rtx pat = NULL_RTX;
|
||||
enum insn_code code = CODE_FOR_nothing;
|
||||
int numregs = 0;
|
||||
@ -656,6 +581,128 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
|
||||
if (regno_save_mem[regno][1] == 0)
|
||||
abort ();
|
||||
|
||||
/* Get the pattern to emit and update our status.
|
||||
|
||||
See if we can restore `maxrestore' registers at once. Work
|
||||
backwards to the single register case. */
|
||||
for (i = maxrestore; i > 0; i--)
|
||||
{
|
||||
int j, k;
|
||||
int ok = 1;
|
||||
|
||||
if (regno_save_mem[regno][i] == 0)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
if (! TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
|
||||
{
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
/* Must do this one restore at a time */
|
||||
if (! ok)
|
||||
continue;
|
||||
|
||||
pat = gen_rtx_SET (VOIDmode,
|
||||
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
|
||||
regno),
|
||||
regno_save_mem[regno][i]);
|
||||
code = reg_restore_code[regno][i];
|
||||
|
||||
/* Clear status for all registers we restored. */
|
||||
for (k = 0; k < i; k++)
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k);
|
||||
n_regs_saved--;
|
||||
}
|
||||
|
||||
numregs = i;
|
||||
break;
|
||||
}
|
||||
|
||||
insert_one_insn (chain, before_p, code, pat);
|
||||
|
||||
/* Tell our callers how many extra registers we saved/restored */
|
||||
return numregs - 1;
|
||||
}
|
||||
|
||||
/* Like insert_restore above, but save registers instead. */
|
||||
static int
|
||||
insert_save (chain, before_p, regno, to_save)
|
||||
struct insn_chain *chain;
|
||||
int before_p;
|
||||
int regno;
|
||||
HARD_REG_SET *to_save;
|
||||
{
|
||||
int i;
|
||||
rtx pat = NULL_RTX;
|
||||
enum insn_code code = CODE_FOR_nothing;
|
||||
int numregs = 0;
|
||||
|
||||
/* A common failure mode if register status is not correct in the RTL
|
||||
is for this routine to be called with a REGNO we didn't expect to
|
||||
save. That will cause us to write an insn with a (nil) SET_DEST
|
||||
or SET_SRC. Instead of doing so and causing a crash later, check
|
||||
for this common case and abort here instead. This will remove one
|
||||
step in debugging such problems. */
|
||||
|
||||
if (regno_save_mem[regno][1] == 0)
|
||||
abort ();
|
||||
|
||||
/* Get the pattern to emit and update our status.
|
||||
|
||||
See if we can save several registers with a single instruction.
|
||||
Work backwards to the single register case. */
|
||||
for (i = MOVE_MAX_WORDS; i > 0; i--)
|
||||
{
|
||||
int j, k;
|
||||
int ok = 1;
|
||||
if (regno_save_mem[regno][i] == 0)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < i; j++)
|
||||
if (! TEST_HARD_REG_BIT (*to_save, regno + j))
|
||||
{
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
/* Must do this one save at a time */
|
||||
if (! ok)
|
||||
continue;
|
||||
|
||||
pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
|
||||
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
|
||||
regno));
|
||||
code = reg_save_code[regno][i];
|
||||
|
||||
/* Set hard_regs_saved for all the registers we saved. */
|
||||
for (k = 0; k < i; k++)
|
||||
{
|
||||
SET_HARD_REG_BIT (hard_regs_saved, regno + k);
|
||||
n_regs_saved++;
|
||||
}
|
||||
|
||||
numregs = i;
|
||||
break;
|
||||
}
|
||||
|
||||
insert_one_insn (chain, before_p, code, pat);
|
||||
|
||||
/* Tell our callers how many extra registers we saved/restored */
|
||||
return numregs - 1;
|
||||
}
|
||||
|
||||
/* Emit a new caller-save insn and set the code. */
|
||||
static void
|
||||
insert_one_insn (chain, before_p, code, pat)
|
||||
struct insn_chain *chain;
|
||||
int before_p;
|
||||
enum insn_code code;
|
||||
rtx pat;
|
||||
{
|
||||
rtx insn = chain->insn;
|
||||
struct insn_chain *new;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
/* If INSN references CC0, put our insns in front of the insn that sets
|
||||
CC0. This is always safe, since the only way we could be passed an
|
||||
@ -664,100 +711,47 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
|
||||
reference CC0. Guard against non-INSN's like CODE_LABEL. */
|
||||
|
||||
if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
|
||||
&& before_p
|
||||
&& reg_referenced_p (cc0_rtx, PATTERN (insn)))
|
||||
insn = prev_nonnote_insn (insn);
|
||||
chain = chain->prev, insn = chain->insn;
|
||||
#endif
|
||||
|
||||
/* Get the pattern to emit and update our status. */
|
||||
if (save_p)
|
||||
new = new_insn_chain ();
|
||||
if (before_p)
|
||||
{
|
||||
int i, j, k;
|
||||
int ok;
|
||||
new->prev = chain->prev;
|
||||
if (new->prev != 0)
|
||||
new->prev->next = new;
|
||||
else
|
||||
reload_insn_chain = new;
|
||||
|
||||
/* See if we can save several registers with a single instruction.
|
||||
Work backwards to the single register case. */
|
||||
for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
|
||||
{
|
||||
ok = 1;
|
||||
if (regno_save_mem[regno][i] != 0)
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
|
||||
|| ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
|
||||
|| TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* Must do this one save at a time */
|
||||
if (! ok)
|
||||
continue;
|
||||
|
||||
pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
|
||||
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
|
||||
regno));
|
||||
code = reg_save_code[regno][i];
|
||||
|
||||
/* Set hard_regs_saved for all the registers we saved. */
|
||||
for (k = 0; k < i; k++)
|
||||
{
|
||||
SET_HARD_REG_BIT (hard_regs_saved, regno + k);
|
||||
SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
|
||||
n_regs_saved++;
|
||||
}
|
||||
|
||||
numregs = i;
|
||||
break;
|
||||
}
|
||||
chain->prev = new;
|
||||
new->next = chain;
|
||||
new->insn = emit_insn_before (pat, insn);
|
||||
/* ??? It would be nice if we could exclude the already / still saved
|
||||
registers from the live sets. */
|
||||
COPY_REG_SET (new->live_before, chain->live_before);
|
||||
COPY_REG_SET (new->live_after, chain->live_before);
|
||||
if (chain->insn == BLOCK_HEAD (chain->block))
|
||||
BLOCK_HEAD (chain->block) = new->insn;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i, j, k;
|
||||
int ok;
|
||||
|
||||
/* See if we can restore `maxrestore' registers at once. Work
|
||||
backwards to the single register case. */
|
||||
for (i = maxrestore; i > 0; i--)
|
||||
{
|
||||
ok = 1;
|
||||
if (regno_save_mem[regno][i])
|
||||
for (j = 0; j < i; j++)
|
||||
{
|
||||
if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* Must do this one restore at a time */
|
||||
if (! ok)
|
||||
continue;
|
||||
|
||||
pat = gen_rtx_SET (VOIDmode,
|
||||
gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
|
||||
regno),
|
||||
regno_save_mem[regno][i]);
|
||||
code = reg_restore_code[regno][i];
|
||||
|
||||
|
||||
/* Clear status for all registers we restored. */
|
||||
for (k = 0; k < i; k++)
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
|
||||
n_regs_saved--;
|
||||
}
|
||||
|
||||
numregs = i;
|
||||
break;
|
||||
}
|
||||
new->next = chain->next;
|
||||
if (new->next != 0)
|
||||
new->next->prev = new;
|
||||
chain->next = new;
|
||||
new->prev = chain;
|
||||
new->insn = emit_insn_after (pat, insn);
|
||||
/* ??? It would be nice if we could exclude the already / still saved
|
||||
registers from the live sets, and observe REG_UNUSED notes. */
|
||||
COPY_REG_SET (new->live_before, chain->live_after);
|
||||
COPY_REG_SET (new->live_after, chain->live_after);
|
||||
if (chain->insn == BLOCK_END (chain->block))
|
||||
BLOCK_END (chain->block) = new->insn;
|
||||
}
|
||||
/* Emit the insn and set the code and mode. */
|
||||
new->block = chain->block;
|
||||
new->is_caller_save_insn = 1;
|
||||
|
||||
insn = emit_insn_before (pat, insn);
|
||||
PUT_MODE (insn, insn_mode);
|
||||
INSN_CODE (insn) = code;
|
||||
|
||||
/* Tell our callers how many extra registers we saved/restored */
|
||||
return numregs - 1;
|
||||
INSN_CODE (new->insn) = code;
|
||||
}
|
||||
|
2115
contrib/gcc/calls.c
2115
contrib/gcc/calls.c
File diff suppressed because it is too large
Load Diff
1439
contrib/gcc/cccp.c
1439
contrib/gcc/cccp.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Parse C expressions for CCCP.
|
||||
Copyright (C) 1987, 1992, 94 - 97, 1998 Free Software Foundation.
|
||||
Copyright (C) 1987, 92, 94-98, 1999 Free Software Foundation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
@ -26,25 +26,16 @@ Boston, MA 02111-1307, USA.
|
||||
|
||||
%{
|
||||
#include "config.h"
|
||||
#ifdef __STDC__
|
||||
# include <stdarg.h>
|
||||
#else
|
||||
# include <varargs.h>
|
||||
#endif
|
||||
|
||||
#define PRINTF_PROTO(ARGS, m, n) PVPROTO (ARGS) ATTRIBUTE_PRINTF(m, n)
|
||||
|
||||
#define PRINTF_PROTO_1(ARGS) PRINTF_PROTO(ARGS, 1, 2)
|
||||
|
||||
#include "system.h"
|
||||
#include "intl.h"
|
||||
#include <setjmp.h>
|
||||
/* #define YYDEBUG 1 */
|
||||
|
||||
#ifdef MULTIBYTE_CHARS
|
||||
#include "mbchar.h"
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include "gansidecl.h"
|
||||
#endif /* MULTIBYTE_CHARS */
|
||||
|
||||
typedef unsigned char U_CHAR;
|
||||
|
||||
@ -56,44 +47,12 @@ struct arglist {
|
||||
int argno;
|
||||
};
|
||||
|
||||
/* Find the largest host integer type and set its size and type.
|
||||
Watch out: on some crazy hosts `long' is shorter than `int'. */
|
||||
|
||||
#ifndef HOST_WIDE_INT
|
||||
# if HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
# define HOST_WIDE_INT intmax_t
|
||||
# define unsigned_HOST_WIDE_INT uintmax_t
|
||||
# else
|
||||
# if (HOST_BITS_PER_LONG <= HOST_BITS_PER_INT && HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_INT)
|
||||
# define HOST_WIDE_INT int
|
||||
# else
|
||||
# if (HOST_BITS_PER_LONGLONG <= HOST_BITS_PER_LONG || ! (defined LONG_LONG_MAX || defined LLONG_MAX))
|
||||
# define HOST_WIDE_INT long
|
||||
# else
|
||||
# define HOST_WIDE_INT long long
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef unsigned_HOST_WIDE_INT
|
||||
#define unsigned_HOST_WIDE_INT unsigned HOST_WIDE_INT
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
#define CHAR_BIT 8
|
||||
#endif
|
||||
|
||||
#ifndef HOST_BITS_PER_WIDE_INT
|
||||
#define HOST_BITS_PER_WIDE_INT (CHAR_BIT * sizeof (HOST_WIDE_INT))
|
||||
#endif
|
||||
|
||||
HOST_WIDE_INT parse_c_expression PROTO((char *, int));
|
||||
HOST_WIDEST_INT parse_c_expression PROTO((char *, int));
|
||||
|
||||
static int yylex PROTO((void));
|
||||
static void yyerror PROTO((char *)) __attribute__ ((noreturn));
|
||||
static HOST_WIDE_INT expression_value;
|
||||
static void yyerror PVPROTO((const char *, ...))
|
||||
ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
|
||||
static HOST_WIDEST_INT expression_value;
|
||||
#ifdef TEST_EXP_READER
|
||||
static int expression_signedp;
|
||||
#endif
|
||||
@ -154,13 +113,13 @@ extern int c89;
|
||||
#define MAX_WCHAR_TYPE_SIZE WCHAR_TYPE_SIZE
|
||||
#endif
|
||||
|
||||
#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
|
||||
? (~ (~ (HOST_WIDE_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
|
||||
: ~ (HOST_WIDE_INT) 0)
|
||||
#define MAX_CHAR_TYPE_MASK (MAX_CHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
|
||||
? (~ (~ (HOST_WIDEST_INT) 0 << MAX_CHAR_TYPE_SIZE)) \
|
||||
: ~ (HOST_WIDEST_INT) 0)
|
||||
|
||||
#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDE_INT \
|
||||
? ~ (~ (HOST_WIDE_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
|
||||
: ~ (HOST_WIDE_INT) 0)
|
||||
#define MAX_WCHAR_TYPE_MASK (MAX_WCHAR_TYPE_SIZE < HOST_BITS_PER_WIDEST_INT \
|
||||
? ~ (~ (HOST_WIDEST_INT) 0 << MAX_WCHAR_TYPE_SIZE) \
|
||||
: ~ (HOST_WIDEST_INT) 0)
|
||||
|
||||
/* Suppose A1 + B1 = SUM1, using 2's complement arithmetic ignoring overflow.
|
||||
Suppose A, B and SUM have the same respective signs as A1, B1, and SUM1.
|
||||
@ -174,17 +133,17 @@ extern int c89;
|
||||
|
||||
struct constant;
|
||||
|
||||
GENERIC_PTR xmalloc PROTO((size_t));
|
||||
HOST_WIDE_INT parse_escape PROTO((char **, HOST_WIDE_INT));
|
||||
HOST_WIDEST_INT parse_escape PROTO((char **, HOST_WIDEST_INT));
|
||||
int check_assertion PROTO((U_CHAR *, int, int, struct arglist *));
|
||||
struct hashnode *lookup PROTO((U_CHAR *, int, int));
|
||||
void error PRINTF_PROTO_1((char *, ...));
|
||||
void pedwarn PRINTF_PROTO_1((char *, ...));
|
||||
void warning PRINTF_PROTO_1((char *, ...));
|
||||
void error PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
|
||||
void verror PROTO((const char *, va_list));
|
||||
void pedwarn PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
|
||||
void warning PVPROTO((const char *, ...)) ATTRIBUTE_PRINTF_1;
|
||||
|
||||
static int parse_number PROTO((int));
|
||||
static HOST_WIDE_INT left_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
|
||||
static HOST_WIDE_INT right_shift PROTO((struct constant *, unsigned_HOST_WIDE_INT));
|
||||
static HOST_WIDEST_INT left_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
|
||||
static HOST_WIDEST_INT right_shift PROTO((struct constant *, unsigned HOST_WIDEST_INT));
|
||||
static void integer_overflow PROTO((void));
|
||||
|
||||
/* `signedp' values */
|
||||
@ -193,7 +152,7 @@ static void integer_overflow PROTO((void));
|
||||
%}
|
||||
|
||||
%union {
|
||||
struct constant {HOST_WIDE_INT value; int signedp;} integer;
|
||||
struct constant {HOST_WIDEST_INT value; int signedp;} integer;
|
||||
struct name {U_CHAR *address; int length;} name;
|
||||
struct arglist *keywords;
|
||||
}
|
||||
@ -280,7 +239,7 @@ exp : exp '*' exp
|
||||
integer_overflow ();
|
||||
}
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
* $3.value); }
|
||||
| exp '/' exp
|
||||
{ if ($3.value == 0)
|
||||
@ -297,7 +256,7 @@ exp : exp '*' exp
|
||||
integer_overflow ();
|
||||
}
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
/ $3.value); }
|
||||
| exp '%' exp
|
||||
{ if ($3.value == 0)
|
||||
@ -310,7 +269,7 @@ exp : exp '*' exp
|
||||
if ($$.signedp)
|
||||
$$.value = $1.value % $3.value;
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
% $3.value); }
|
||||
| exp '+' exp
|
||||
{ $$.value = $1.value + $3.value;
|
||||
@ -347,28 +306,28 @@ exp : exp '*' exp
|
||||
if ($1.signedp & $3.signedp)
|
||||
$$.value = $1.value <= $3.value;
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
<= $3.value); }
|
||||
| exp GEQ exp
|
||||
{ $$.signedp = SIGNED;
|
||||
if ($1.signedp & $3.signedp)
|
||||
$$.value = $1.value >= $3.value;
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
>= $3.value); }
|
||||
| exp '<' exp
|
||||
{ $$.signedp = SIGNED;
|
||||
if ($1.signedp & $3.signedp)
|
||||
$$.value = $1.value < $3.value;
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
< $3.value); }
|
||||
| exp '>' exp
|
||||
{ $$.signedp = SIGNED;
|
||||
if ($1.signedp & $3.signedp)
|
||||
$$.value = $1.value > $3.value;
|
||||
else
|
||||
$$.value = ((unsigned_HOST_WIDE_INT) $1.value
|
||||
$$.value = ((unsigned HOST_WIDEST_INT) $1.value
|
||||
> $3.value); }
|
||||
| exp '&' exp
|
||||
{ $$.value = $1.value & $3.value;
|
||||
@ -451,7 +410,7 @@ parse_number (olen)
|
||||
{
|
||||
register char *p = lexptr;
|
||||
register int c;
|
||||
register unsigned_HOST_WIDE_INT n = 0, nd, max_over_base;
|
||||
register unsigned HOST_WIDEST_INT n = 0, nd, max_over_base;
|
||||
register int base = 10;
|
||||
register int len = olen;
|
||||
register int overflow = 0;
|
||||
@ -469,7 +428,7 @@ parse_number (olen)
|
||||
}
|
||||
}
|
||||
|
||||
max_over_base = (unsigned_HOST_WIDE_INT) -1 / base;
|
||||
max_over_base = (unsigned HOST_WIDEST_INT) -1 / base;
|
||||
|
||||
for (; len > 0; len--) {
|
||||
c = *p++;
|
||||
@ -498,12 +457,9 @@ parse_number (olen)
|
||||
else {
|
||||
if (c == '.' || c == 'e' || c == 'E' || c == 'p' || c == 'P')
|
||||
yyerror ("Floating point numbers not allowed in #if expressions");
|
||||
else {
|
||||
char *buf = (char *) alloca (p - lexptr + 40);
|
||||
sprintf (buf, "missing white space after number `%.*s'",
|
||||
else
|
||||
yyerror ("missing white space after number `%.*s'",
|
||||
(int) (p - lexptr - 1), lexptr);
|
||||
yyerror (buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (--len == 0)
|
||||
@ -527,7 +483,7 @@ parse_number (olen)
|
||||
pedwarn ("integer constant out of range");
|
||||
|
||||
/* If too big to be signed, consider it unsigned. */
|
||||
if (((HOST_WIDE_INT) n & yylval.integer.signedp) < 0)
|
||||
if (((HOST_WIDEST_INT) n & yylval.integer.signedp) < 0)
|
||||
{
|
||||
if (base == 10)
|
||||
warning ("integer constant is so large that it is unsigned");
|
||||
@ -540,7 +496,7 @@ parse_number (olen)
|
||||
}
|
||||
|
||||
struct token {
|
||||
char *operator;
|
||||
const char *operator;
|
||||
int token;
|
||||
};
|
||||
|
||||
@ -568,7 +524,7 @@ yylex ()
|
||||
register unsigned char *tokstart;
|
||||
register struct token *toktab;
|
||||
int wide_flag;
|
||||
HOST_WIDE_INT mask;
|
||||
HOST_WIDEST_INT mask;
|
||||
|
||||
retry:
|
||||
|
||||
@ -580,11 +536,7 @@ yylex ()
|
||||
if (c == *toktab->operator && tokstart[1] == toktab->operator[1]) {
|
||||
lexptr += 2;
|
||||
if (toktab->token == ERROR)
|
||||
{
|
||||
char *buf = (char *) alloca (40);
|
||||
sprintf (buf, "`%s' not allowed in operand of `#if'", toktab->operator);
|
||||
yyerror (buf);
|
||||
}
|
||||
yyerror ("`%s' not allowed in operand of `#if'", toktab->operator);
|
||||
return toktab->token;
|
||||
}
|
||||
|
||||
@ -639,25 +591,20 @@ yylex ()
|
||||
handles multicharacter constants and wide characters.
|
||||
It is mostly copied from c-lex.c. */
|
||||
{
|
||||
register HOST_WIDE_INT result = 0;
|
||||
register HOST_WIDEST_INT result = 0;
|
||||
register int num_chars = 0;
|
||||
int chars_seen = 0;
|
||||
unsigned width = MAX_CHAR_TYPE_SIZE;
|
||||
int max_chars;
|
||||
char *token_buffer;
|
||||
|
||||
if (wide_flag)
|
||||
{
|
||||
width = MAX_WCHAR_TYPE_SIZE;
|
||||
#ifdef MULTIBYTE_CHARS
|
||||
max_chars = MB_CUR_MAX;
|
||||
#else
|
||||
max_chars = 1;
|
||||
int longest_char = local_mb_cur_max ();
|
||||
char *token_buffer = (char *) alloca (longest_char);
|
||||
(void) local_mbtowc (NULL_PTR, NULL_PTR, 0);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
max_chars = MAX_LONG_TYPE_SIZE / width;
|
||||
|
||||
token_buffer = (char *) alloca (max_chars + 1);
|
||||
max_chars = MAX_LONG_TYPE_SIZE / width;
|
||||
if (wide_flag)
|
||||
width = MAX_WCHAR_TYPE_SIZE;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@ -666,72 +613,108 @@ yylex ()
|
||||
if (c == '\'' || c == EOF)
|
||||
break;
|
||||
|
||||
++chars_seen;
|
||||
if (c == '\\')
|
||||
{
|
||||
c = parse_escape (&lexptr, mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTIBYTE_CHARS
|
||||
wchar_t wc;
|
||||
int i;
|
||||
int char_len = -1;
|
||||
for (i = 1; i <= longest_char; ++i)
|
||||
{
|
||||
token_buffer[i - 1] = c;
|
||||
char_len = local_mbtowc (& wc, token_buffer, i);
|
||||
if (char_len != -1)
|
||||
break;
|
||||
c = *lexptr++;
|
||||
}
|
||||
if (char_len > 1)
|
||||
{
|
||||
/* mbtowc sometimes needs an extra char before accepting */
|
||||
if (char_len < i)
|
||||
lexptr--;
|
||||
if (! wide_flag)
|
||||
{
|
||||
/* Merge character into result; ignore excess chars. */
|
||||
for (i = 1; i <= char_len; ++i)
|
||||
{
|
||||
if (i > max_chars)
|
||||
break;
|
||||
if (width < HOST_BITS_PER_INT)
|
||||
result = (result << width)
|
||||
| (token_buffer[i - 1]
|
||||
& ((1 << width) - 1));
|
||||
else
|
||||
result = token_buffer[i - 1];
|
||||
}
|
||||
num_chars += char_len;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (char_len == -1)
|
||||
warning ("Ignoring invalid multibyte character");
|
||||
}
|
||||
if (wide_flag)
|
||||
c = wc;
|
||||
#endif /* ! MULTIBYTE_CHARS */
|
||||
}
|
||||
|
||||
num_chars++;
|
||||
if (wide_flag)
|
||||
{
|
||||
if (chars_seen == 1) /* only keep the first one */
|
||||
result = c;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Merge character into result; ignore excess chars. */
|
||||
num_chars++;
|
||||
if (num_chars <= max_chars)
|
||||
{
|
||||
if (width < HOST_BITS_PER_WIDE_INT)
|
||||
result = (result << width) | c;
|
||||
if (width < HOST_BITS_PER_INT)
|
||||
result = (result << width) | (c & ((1 << width) - 1));
|
||||
else
|
||||
result = c;
|
||||
token_buffer[num_chars - 1] = c;
|
||||
}
|
||||
}
|
||||
|
||||
token_buffer[num_chars] = 0;
|
||||
|
||||
if (c != '\'')
|
||||
error ("malformatted character constant");
|
||||
else if (num_chars == 0)
|
||||
else if (chars_seen == 0)
|
||||
error ("empty character constant");
|
||||
else if (num_chars > max_chars)
|
||||
{
|
||||
num_chars = max_chars;
|
||||
error ("character constant too long");
|
||||
}
|
||||
else if (num_chars != 1 && ! traditional)
|
||||
else if (chars_seen != 1 && ! traditional)
|
||||
warning ("multi-character character constant");
|
||||
|
||||
/* If char type is signed, sign-extend the constant. */
|
||||
if (! wide_flag)
|
||||
{
|
||||
int num_bits = num_chars * width;
|
||||
|
||||
if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
|
||||
if (num_bits == 0)
|
||||
/* We already got an error; avoid invalid shift. */
|
||||
yylval.integer.value = 0;
|
||||
else if (lookup ((U_CHAR *) "__CHAR_UNSIGNED__",
|
||||
sizeof ("__CHAR_UNSIGNED__") - 1, -1)
|
||||
|| ((result >> (num_bits - 1)) & 1) == 0)
|
||||
yylval.integer.value
|
||||
= result & (~ (unsigned_HOST_WIDE_INT) 0
|
||||
>> (HOST_BITS_PER_WIDE_INT - num_bits));
|
||||
= result & (~ (unsigned HOST_WIDEST_INT) 0
|
||||
>> (HOST_BITS_PER_WIDEST_INT - num_bits));
|
||||
else
|
||||
yylval.integer.value
|
||||
= result | ~(~ (unsigned_HOST_WIDE_INT) 0
|
||||
>> (HOST_BITS_PER_WIDE_INT - num_bits));
|
||||
= result | ~(~ (unsigned HOST_WIDEST_INT) 0
|
||||
>> (HOST_BITS_PER_WIDEST_INT - num_bits));
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MULTIBYTE_CHARS
|
||||
/* Set the initial shift state and convert the next sequence. */
|
||||
result = 0;
|
||||
/* In all locales L'\0' is zero and mbtowc will return zero,
|
||||
so don't use it. */
|
||||
if (num_chars > 1
|
||||
|| (num_chars == 1 && token_buffer[0] != '\0'))
|
||||
{
|
||||
wchar_t wc;
|
||||
(void) mbtowc (NULL_PTR, NULL_PTR, 0);
|
||||
if (mbtowc (& wc, token_buffer, num_chars) == num_chars)
|
||||
result = wc;
|
||||
else
|
||||
pedwarn ("Ignoring invalid multibyte character");
|
||||
}
|
||||
#endif
|
||||
yylval.integer.value = result;
|
||||
}
|
||||
}
|
||||
@ -854,10 +837,10 @@ yylex ()
|
||||
If \ is followed by 000, we return 0 and leave the string pointer
|
||||
after the zeros. A value of 0 does not mean end of string. */
|
||||
|
||||
HOST_WIDE_INT
|
||||
HOST_WIDEST_INT
|
||||
parse_escape (string_ptr, result_mask)
|
||||
char **string_ptr;
|
||||
HOST_WIDE_INT result_mask;
|
||||
HOST_WIDEST_INT result_mask;
|
||||
{
|
||||
register int c = *(*string_ptr)++;
|
||||
switch (c)
|
||||
@ -896,7 +879,7 @@ parse_escape (string_ptr, result_mask)
|
||||
case '6':
|
||||
case '7':
|
||||
{
|
||||
register HOST_WIDE_INT i = c - '0';
|
||||
register HOST_WIDEST_INT i = c - '0';
|
||||
register int count = 0;
|
||||
while (++count < 3)
|
||||
{
|
||||
@ -918,7 +901,7 @@ parse_escape (string_ptr, result_mask)
|
||||
}
|
||||
case 'x':
|
||||
{
|
||||
register unsigned_HOST_WIDE_INT i = 0, overflow = 0;
|
||||
register unsigned HOST_WIDEST_INT i = 0, overflow = 0;
|
||||
register int digits_found = 0, digit;
|
||||
for (;;)
|
||||
{
|
||||
@ -952,15 +935,6 @@ parse_escape (string_ptr, result_mask)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror (s)
|
||||
char *s;
|
||||
{
|
||||
error ("%s", s);
|
||||
skip_evaluation = 0;
|
||||
longjmp (parse_return_error, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
integer_overflow ()
|
||||
{
|
||||
@ -968,31 +942,31 @@ integer_overflow ()
|
||||
pedwarn ("integer overflow in preprocessor expression");
|
||||
}
|
||||
|
||||
static HOST_WIDE_INT
|
||||
static HOST_WIDEST_INT
|
||||
left_shift (a, b)
|
||||
struct constant *a;
|
||||
unsigned_HOST_WIDE_INT b;
|
||||
unsigned HOST_WIDEST_INT b;
|
||||
{
|
||||
/* It's unclear from the C standard whether shifts can overflow.
|
||||
The following code ignores overflow; perhaps a C standard
|
||||
interpretation ruling is needed. */
|
||||
if (b >= HOST_BITS_PER_WIDE_INT)
|
||||
if (b >= HOST_BITS_PER_WIDEST_INT)
|
||||
return 0;
|
||||
else
|
||||
return (unsigned_HOST_WIDE_INT) a->value << b;
|
||||
return (unsigned HOST_WIDEST_INT) a->value << b;
|
||||
}
|
||||
|
||||
static HOST_WIDE_INT
|
||||
static HOST_WIDEST_INT
|
||||
right_shift (a, b)
|
||||
struct constant *a;
|
||||
unsigned_HOST_WIDE_INT b;
|
||||
unsigned HOST_WIDEST_INT b;
|
||||
{
|
||||
if (b >= HOST_BITS_PER_WIDE_INT)
|
||||
return a->signedp ? a->value >> (HOST_BITS_PER_WIDE_INT - 1) : 0;
|
||||
if (b >= HOST_BITS_PER_WIDEST_INT)
|
||||
return a->signedp ? a->value >> (HOST_BITS_PER_WIDEST_INT - 1) : 0;
|
||||
else if (a->signedp)
|
||||
return a->value >> b;
|
||||
else
|
||||
return (unsigned_HOST_WIDE_INT) a->value >> b;
|
||||
return (unsigned HOST_WIDEST_INT) a->value >> b;
|
||||
}
|
||||
|
||||
/* This page contains the entry point to this file. */
|
||||
@ -1005,7 +979,7 @@ right_shift (a, b)
|
||||
We do not support C comments. They should be removed before
|
||||
this function is called. */
|
||||
|
||||
HOST_WIDE_INT
|
||||
HOST_WIDEST_INT
|
||||
parse_c_expression (string, warn_undefined)
|
||||
char *string;
|
||||
int warn_undefined;
|
||||
@ -1027,6 +1001,27 @@ parse_c_expression (string, warn_undefined)
|
||||
|
||||
return expression_value; /* set by yyparse () */
|
||||
}
|
||||
|
||||
static void
|
||||
yyerror VPROTO ((const char * msgid, ...))
|
||||
{
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
const char * msgid;
|
||||
#endif
|
||||
va_list args;
|
||||
|
||||
VA_START (args, msgid);
|
||||
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
msgid = va_arg (args, const char *);
|
||||
#endif
|
||||
|
||||
verror (msgid, args);
|
||||
va_end (args);
|
||||
skip_evaluation = 0;
|
||||
longjmp (parse_return_error, 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef TEST_EXP_READER
|
||||
|
||||
@ -1036,10 +1031,11 @@ extern int yydebug;
|
||||
|
||||
int pedantic;
|
||||
int traditional;
|
||||
int c89;
|
||||
|
||||
int main PROTO((int, char **));
|
||||
static void initialize_random_junk PROTO((void));
|
||||
static void print_unsigned_host_wide_int PROTO((unsigned_HOST_WIDE_INT));
|
||||
static void print_unsigned_host_widest_int PROTO((unsigned HOST_WIDEST_INT));
|
||||
|
||||
/* Main program for testing purposes. */
|
||||
int
|
||||
@ -1049,12 +1045,13 @@ main (argc, argv)
|
||||
{
|
||||
int n, c;
|
||||
char buf[1024];
|
||||
unsigned_HOST_WIDE_INT u;
|
||||
unsigned HOST_WIDEST_INT u;
|
||||
|
||||
pedantic = 1 < argc;
|
||||
traditional = 2 < argc;
|
||||
c89 = 3 < argc;
|
||||
#if YYDEBUG
|
||||
yydebug = 3 < argc;
|
||||
yydebug = 4 < argc;
|
||||
#endif
|
||||
initialize_random_junk ();
|
||||
|
||||
@ -1067,7 +1064,7 @@ main (argc, argv)
|
||||
break;
|
||||
parse_c_expression (buf, 1);
|
||||
printf ("parser returned ");
|
||||
u = (unsigned_HOST_WIDE_INT) expression_value;
|
||||
u = (unsigned HOST_WIDEST_INT) expression_value;
|
||||
if (expression_value < 0 && expression_signedp) {
|
||||
u = -u;
|
||||
printf ("-");
|
||||
@ -1075,7 +1072,7 @@ main (argc, argv)
|
||||
if (u == 0)
|
||||
printf ("0");
|
||||
else
|
||||
print_unsigned_host_wide_int (u);
|
||||
print_unsigned_host_widest_int (u);
|
||||
if (! expression_signedp)
|
||||
printf("u");
|
||||
printf ("\n");
|
||||
@ -1085,11 +1082,11 @@ main (argc, argv)
|
||||
}
|
||||
|
||||
static void
|
||||
print_unsigned_host_wide_int (u)
|
||||
unsigned_HOST_WIDE_INT u;
|
||||
print_unsigned_host_widest_int (u)
|
||||
unsigned HOST_WIDEST_INT u;
|
||||
{
|
||||
if (u) {
|
||||
print_unsigned_host_wide_int (u / 10);
|
||||
print_unsigned_host_widest_int (u / 10);
|
||||
putchar ('0' + (int) (u % 10));
|
||||
}
|
||||
}
|
||||
@ -1137,65 +1134,66 @@ initialize_random_junk ()
|
||||
}
|
||||
|
||||
void
|
||||
error VPROTO ((char * msg, ...))
|
||||
error VPROTO ((char * msgid, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char * msg;
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
char * msgid;
|
||||
#endif
|
||||
va_list args;
|
||||
|
||||
VA_START (args, msg);
|
||||
|
||||
#ifndef __STDC__
|
||||
msg = va_arg (args, char *);
|
||||
VA_START (args, msgid);
|
||||
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
msgid = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
|
||||
fprintf (stderr, "error: ");
|
||||
vfprintf (stderr, msg, args);
|
||||
vfprintf (stderr, _(msgid), args);
|
||||
fprintf (stderr, "\n");
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
pedwarn VPROTO ((char * msg, ...))
|
||||
pedwarn VPROTO ((char * msgid, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char * msg;
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
char * msgid;
|
||||
#endif
|
||||
va_list args;
|
||||
|
||||
VA_START (args, msg);
|
||||
|
||||
#ifndef __STDC__
|
||||
msg = va_arg (args, char *);
|
||||
VA_START (args, msgid);
|
||||
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
msgid = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
|
||||
fprintf (stderr, "pedwarn: ");
|
||||
vfprintf (stderr, msg, args);
|
||||
vfprintf (stderr, _(msgid), args);
|
||||
fprintf (stderr, "\n");
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
void
|
||||
warning VPROTO ((char * msg, ...))
|
||||
warning VPROTO ((char * msgid, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char * msg;
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
char * msgid;
|
||||
#endif
|
||||
va_list args;
|
||||
|
||||
VA_START (args, msg);
|
||||
|
||||
#ifndef __STDC__
|
||||
msg = va_arg (args, char *);
|
||||
VA_START (args, msgid);
|
||||
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
msgid = va_arg (args, char *);
|
||||
#endif
|
||||
|
||||
|
||||
fprintf (stderr, "warning: ");
|
||||
vfprintf (stderr, msg, args);
|
||||
vfprintf (stderr, _(msgid), args);
|
||||
fprintf (stderr, "\n");
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
check_assertion (name, sym_length, tokens_specified, tokens)
|
||||
U_CHAR *name;
|
||||
@ -1215,10 +1213,10 @@ lookup (name, len, hash)
|
||||
return (DEFAULT_SIGNED_CHAR) ? 0 : ((struct hashnode *) -1);
|
||||
}
|
||||
|
||||
GENERIC_PTR
|
||||
PTR
|
||||
xmalloc (size)
|
||||
size_t size;
|
||||
size_t size;
|
||||
{
|
||||
return (GENERIC_PTR) malloc (size);
|
||||
return (PTR) malloc (size);
|
||||
}
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
36
contrib/gcc/collect2.h
Normal file
36
contrib/gcc/collect2.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* Header file for collect/tlink routines.
|
||||
Copyright (C) 1998 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. */
|
||||
|
||||
#ifndef __COLLECT2_H__
|
||||
#define __COLLECT2_H__
|
||||
|
||||
extern void do_tlink PARAMS ((char **, char **));
|
||||
|
||||
extern void collect_execute PARAMS ((char *, char **, char *));
|
||||
|
||||
extern void collect_exit PARAMS ((int)) ATTRIBUTE_NORETURN;
|
||||
|
||||
extern int collect_wait PARAMS ((char *));
|
||||
|
||||
extern void dump_file PARAMS ((char *));
|
||||
|
||||
extern int file_exists PARAMS ((char *));
|
||||
|
||||
#endif /* ! __COLLECT2_H__ */
|
@ -75,16 +75,8 @@ Boston, MA 02111-1307, USA. */
|
||||
combine anyway. */
|
||||
|
||||
#include "config.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
/* stdio.h must precede rtl.h for FFS. */
|
||||
#include "system.h"
|
||||
|
||||
#include "rtl.h"
|
||||
#include "rtl.h" /* stdio.h must precede rtl.h for FFS. */
|
||||
#include "flags.h"
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
@ -434,7 +426,7 @@ static int merge_outer_ops PROTO((enum rtx_code *, HOST_WIDE_INT *,
|
||||
enum machine_mode, int *));
|
||||
static rtx simplify_shift_const PROTO((rtx, enum rtx_code, enum machine_mode,
|
||||
rtx, int));
|
||||
static int recog_for_combine PROTO((rtx *, rtx, rtx *, int *));
|
||||
static int recog_for_combine PROTO((rtx *, rtx, rtx *));
|
||||
static rtx gen_lowpart_for_combine PROTO((enum machine_mode, rtx));
|
||||
static rtx gen_rtx_combine PVPROTO((enum rtx_code code, enum machine_mode mode,
|
||||
...));
|
||||
@ -581,7 +573,7 @@ combine_instructions (f, nregs)
|
||||
|
||||
/* If INSN starts a new basic block, update our basic block number. */
|
||||
if (this_basic_block + 1 < n_basic_blocks
|
||||
&& basic_block_head[this_basic_block + 1] == insn)
|
||||
&& BLOCK_HEAD (this_basic_block + 1) == insn)
|
||||
this_basic_block++;
|
||||
|
||||
if (GET_CODE (insn) == CODE_LABEL)
|
||||
@ -682,6 +674,9 @@ combine_instructions (f, nregs)
|
||||
total_successes += combine_successes;
|
||||
|
||||
nonzero_sign_valid = 0;
|
||||
|
||||
/* Make recognizer allow volatile MEMs again. */
|
||||
init_recog ();
|
||||
}
|
||||
|
||||
/* Wipe the reg_last_xxx arrays in preparation for another pass. */
|
||||
@ -749,7 +744,7 @@ set_nonzero_bits_and_sign_copies (x, set)
|
||||
&& REGNO (x) >= FIRST_PSEUDO_REGISTER
|
||||
/* If this register is undefined at the start of the file, we can't
|
||||
say what its contents were. */
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], REGNO (x))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
|
||||
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
if (set == 0 || GET_CODE (set) == CLOBBER)
|
||||
@ -824,7 +819,8 @@ static int
|
||||
can_combine_p (insn, i3, pred, succ, pdest, psrc)
|
||||
rtx insn;
|
||||
rtx i3;
|
||||
rtx pred, succ;
|
||||
rtx pred ATTRIBUTE_UNUSED;
|
||||
rtx succ;
|
||||
rtx *pdest, *psrc;
|
||||
{
|
||||
int i;
|
||||
@ -958,8 +954,14 @@ can_combine_p (insn, i3, pred, succ, pdest, psrc)
|
||||
/* Don't substitute into an incremented register. */
|
||||
|| FIND_REG_INC_NOTE (i3, dest)
|
||||
|| (succ && FIND_REG_INC_NOTE (succ, dest))
|
||||
#if 0
|
||||
/* Don't combine the end of a libcall into anything. */
|
||||
/* ??? This gives worse code, and appears to be unnecessary, since no
|
||||
pass after flow uses REG_LIBCALL/REG_RETVAL notes. Local-alloc does
|
||||
use REG_RETVAL notes for noconflict blocks, but other code here
|
||||
makes sure that those insns don't disappear. */
|
||||
|| find_reg_note (insn, REG_RETVAL, NULL_RTX)
|
||||
#endif
|
||||
/* Make sure that DEST is not used after SUCC but before I3. */
|
||||
|| (succ && ! all_adjacent
|
||||
&& reg_used_between_p (dest, succ, i3))
|
||||
@ -1354,8 +1356,6 @@ try_combine (i3, i2, i1)
|
||||
int i3_subst_into_i2 = 0;
|
||||
/* Notes that I1, I2 or I3 is a MULT operation. */
|
||||
int have_mult = 0;
|
||||
/* Number of clobbers of SCRATCH we had to add. */
|
||||
int i3_scratches = 0, i2_scratches = 0, other_scratches = 0;
|
||||
|
||||
int maxreg;
|
||||
rtx temp;
|
||||
@ -1371,7 +1371,12 @@ try_combine (i3, i2, i1)
|
||||
if (GET_RTX_CLASS (GET_CODE (i3)) != 'i'
|
||||
|| GET_RTX_CLASS (GET_CODE (i2)) != 'i'
|
||||
|| (i1 && GET_RTX_CLASS (GET_CODE (i1)) != 'i')
|
||||
|| find_reg_note (i3, REG_LIBCALL, NULL_RTX))
|
||||
#if 0
|
||||
/* ??? This gives worse code, and appears to be unnecessary, since no
|
||||
pass after flow uses REG_LIBCALL/REG_RETVAL notes. */
|
||||
|| find_reg_note (i3, REG_LIBCALL, NULL_RTX)
|
||||
#endif
|
||||
)
|
||||
return 0;
|
||||
|
||||
combine_attempts++;
|
||||
@ -1827,8 +1832,7 @@ try_combine (i3, i2, i1)
|
||||
mark_used_regs_combine (newpat);
|
||||
|
||||
/* Is the result of combination a valid instruction? */
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
|
||||
/* If the result isn't valid, see if it is a PARALLEL of two SETs where
|
||||
the second SET's destination is a register that is unused. In that case,
|
||||
@ -1849,8 +1853,7 @@ try_combine (i3, i2, i1)
|
||||
&& asm_noperands (newpat) < 0)
|
||||
{
|
||||
newpat = XVECEXP (newpat, 0, 0);
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
}
|
||||
|
||||
else if (insn_code_number < 0 && GET_CODE (newpat) == PARALLEL
|
||||
@ -1863,8 +1866,7 @@ try_combine (i3, i2, i1)
|
||||
&& asm_noperands (newpat) < 0)
|
||||
{
|
||||
newpat = XVECEXP (newpat, 0, 1);
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
}
|
||||
|
||||
/* If we were combining three insns and the result is a simple SET
|
||||
@ -1933,8 +1935,7 @@ try_combine (i3, i2, i1)
|
||||
if (REGNO (i2dest) >= FIRST_PSEUDO_REGISTER)
|
||||
SUBST (regno_reg_rtx[REGNO (i2dest)], ni2dest);
|
||||
|
||||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes,
|
||||
&i2_scratches);
|
||||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
|
||||
|
||||
/* If I2 or I3 has multiple SETs, we won't know how to track
|
||||
register status, so don't use these insns. If I2's destination
|
||||
@ -1943,8 +1944,8 @@ try_combine (i3, i2, i1)
|
||||
if (i2_code_number >= 0 && i2set && i3set
|
||||
&& (next_real_insn (i2) == i3
|
||||
|| ! reg_used_between_p (SET_DEST (i2set), i2, i3)))
|
||||
insn_code_number = recog_for_combine (&newi3pat, i3, &new_i3_notes,
|
||||
&i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newi3pat, i3,
|
||||
&new_i3_notes);
|
||||
if (insn_code_number >= 0)
|
||||
newpat = newi3pat;
|
||||
|
||||
@ -2031,14 +2032,12 @@ try_combine (i3, i2, i1)
|
||||
|
||||
newi2pat = gen_rtx_combine (SET, VOIDmode, newdest, *split);
|
||||
SUBST (*split, newdest);
|
||||
i2_code_number
|
||||
= recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
|
||||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
|
||||
|
||||
/* If the split point was a MULT and we didn't have one before,
|
||||
don't use one now. */
|
||||
if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult))
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2092,12 +2091,10 @@ try_combine (i3, i2, i1)
|
||||
newpat = XVECEXP (newpat, 0, 1);
|
||||
SUBST (SET_SRC (newpat),
|
||||
gen_lowpart_for_combine (GET_MODE (SET_SRC (newpat)), ni2dest));
|
||||
i2_code_number
|
||||
= recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
|
||||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
|
||||
|
||||
if (i2_code_number >= 0)
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
|
||||
if (insn_code_number >= 0)
|
||||
{
|
||||
@ -2127,7 +2124,7 @@ try_combine (i3, i2, i1)
|
||||
|
||||
for (insn = NEXT_INSN (i3);
|
||||
insn && (this_basic_block == n_basic_blocks - 1
|
||||
|| insn != basic_block_head[this_basic_block + 1]);
|
||||
|| insn != BLOCK_HEAD (this_basic_block + 1));
|
||||
insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||
@ -2184,12 +2181,10 @@ try_combine (i3, i2, i1)
|
||||
newpat = XVECEXP (newpat, 0, 0);
|
||||
}
|
||||
|
||||
i2_code_number
|
||||
= recog_for_combine (&newi2pat, i2, &new_i2_notes, &i2_scratches);
|
||||
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
|
||||
|
||||
if (i2_code_number >= 0)
|
||||
insn_code_number
|
||||
= recog_for_combine (&newpat, i3, &new_i3_notes, &i3_scratches);
|
||||
insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes);
|
||||
}
|
||||
|
||||
/* If it still isn't recognized, fail and change things back the way they
|
||||
@ -2211,9 +2206,8 @@ try_combine (i3, i2, i1)
|
||||
|
||||
CLEAR_HARD_REG_SET (newpat_used_regs);
|
||||
|
||||
other_code_number
|
||||
= recog_for_combine (&other_pat, undobuf.other_insn,
|
||||
&new_other_notes, &other_scratches);
|
||||
other_code_number = recog_for_combine (&other_pat, undobuf.other_insn,
|
||||
&new_other_notes);
|
||||
|
||||
if (other_code_number < 0 && ! check_asm_operands (other_pat))
|
||||
{
|
||||
@ -2316,7 +2310,7 @@ try_combine (i3, i2, i1)
|
||||
SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
|
||||
for (temp = NEXT_INSN (i2);
|
||||
temp && (this_basic_block == n_basic_blocks - 1
|
||||
|| basic_block_head[this_basic_block] != temp);
|
||||
|| BLOCK_HEAD (this_basic_block) != temp);
|
||||
temp = NEXT_INSN (temp))
|
||||
if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
|
||||
for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
|
||||
@ -2496,7 +2490,8 @@ try_combine (i3, i2, i1)
|
||||
regno = REGNO (i2dest);
|
||||
REG_N_SETS (regno)--;
|
||||
if (REG_N_SETS (regno) == 0
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
|
||||
regno))
|
||||
REG_N_REFS (regno) = 0;
|
||||
}
|
||||
}
|
||||
@ -2518,7 +2513,8 @@ try_combine (i3, i2, i1)
|
||||
{
|
||||
REG_N_SETS (regno)--;
|
||||
if (REG_N_SETS (regno) == 0
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
|
||||
regno))
|
||||
REG_N_REFS (regno) = 0;
|
||||
}
|
||||
}
|
||||
@ -2530,12 +2526,6 @@ try_combine (i3, i2, i1)
|
||||
if (newi2pat)
|
||||
note_stores (newi2pat, set_nonzero_bits_and_sign_copies);
|
||||
|
||||
/* If we added any (clobber (scratch)), add them to the max for a
|
||||
block. This is a very pessimistic calculation, since we might
|
||||
have had them already and this might not be the worst block, but
|
||||
it's not worth doing any better. */
|
||||
max_scratch += i3_scratches + i2_scratches + other_scratches;
|
||||
|
||||
/* If I3 is now an unconditional jump, ensure that it has a
|
||||
BARRIER following it since it may have initially been a
|
||||
conditional jump. It may also be the last nonnote insn. */
|
||||
@ -2747,7 +2737,7 @@ find_split_point (loc, insn)
|
||||
if (BITS_BIG_ENDIAN)
|
||||
pos = GET_MODE_BITSIZE (mode) - len - pos;
|
||||
|
||||
if (src == mask)
|
||||
if ((unsigned HOST_WIDE_INT) src == mask)
|
||||
SUBST (SET_SRC (x),
|
||||
gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
|
||||
else
|
||||
@ -3514,9 +3504,8 @@ simplify_rtx (x, op0_mode, last, in_dest)
|
||||
plus_constant (XEXP (inner, 0),
|
||||
(SUBREG_WORD (x) * UNITS_PER_WORD
|
||||
+ endian_offset)));
|
||||
MEM_VOLATILE_P (x) = MEM_VOLATILE_P (inner);
|
||||
RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (inner);
|
||||
MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (inner);
|
||||
MEM_COPY_ATTRIBUTES (x, inner);
|
||||
return x;
|
||||
}
|
||||
|
||||
@ -3821,9 +3810,12 @@ simplify_rtx (x, op0_mode, last, in_dest)
|
||||
return SUBREG_REG (XEXP (x, 0));
|
||||
|
||||
/* If we know that the value is already truncated, we can
|
||||
replace the TRUNCATE with a SUBREG. */
|
||||
if (num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
|
||||
>= GET_MODE_BITSIZE (mode) + 1)
|
||||
replace the TRUNCATE with a SUBREG if TRULY_NOOP_TRUNCATION is
|
||||
nonzero for the corresponding modes. */
|
||||
if (TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
|
||||
GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))))
|
||||
&& num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
|
||||
>= GET_MODE_BITSIZE (mode) + 1)
|
||||
return gen_lowpart_for_combine (mode, XEXP (x, 0));
|
||||
|
||||
/* A truncate of a comparison can be replaced with a subreg if
|
||||
@ -4164,7 +4156,7 @@ simplify_rtx (x, op0_mode, last, in_dest)
|
||||
if (new_code == NE && GET_MODE_CLASS (mode) == MODE_INT
|
||||
&& GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
|
||||
== (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
|
||||
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE(mode)-1))
|
||||
&& op1 == const0_rtx
|
||||
&& mode == GET_MODE (op0)
|
||||
&& (i = exact_log2 (nonzero_bits (op0, mode))) >= 0)
|
||||
@ -4692,9 +4684,8 @@ simplify_set (x)
|
||||
&& exact_log2 (mask = nonzero_bits (op0, GET_MODE (op0))) >= 0)
|
||||
{
|
||||
rtx pat = PATTERN (other_insn), note = 0;
|
||||
int scratches;
|
||||
|
||||
if ((recog_for_combine (&pat, other_insn, ¬e, &scratches) < 0
|
||||
if ((recog_for_combine (&pat, other_insn, ¬e) < 0
|
||||
&& ! check_asm_operands (pat)))
|
||||
{
|
||||
PUT_CODE (*cc_use, old_code);
|
||||
@ -5131,7 +5122,7 @@ simplify_logical (x, last)
|
||||
when STORE_FLAG_VALUE is the sign bit. */
|
||||
if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
|
||||
&& ((STORE_FLAG_VALUE & GET_MODE_MASK (mode))
|
||||
== (HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
|
||||
== (unsigned HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (mode) - 1))
|
||||
&& op1 == const_true_rtx
|
||||
&& GET_RTX_CLASS (GET_CODE (op0)) == '<'
|
||||
&& reversible_comparison_p (op0))
|
||||
@ -5432,6 +5423,24 @@ expand_field_assignment (x)
|
||||
|
||||
compute_mode = GET_MODE (inner);
|
||||
|
||||
/* Don't attempt bitwise arithmetic on non-integral modes. */
|
||||
if (! INTEGRAL_MODE_P (compute_mode))
|
||||
{
|
||||
enum machine_mode imode;
|
||||
|
||||
/* Something is probably seriously wrong if this matches. */
|
||||
if (! FLOAT_MODE_P (compute_mode))
|
||||
break;
|
||||
|
||||
/* Try to find an integral mode to pun with. */
|
||||
imode = mode_for_size (GET_MODE_BITSIZE (compute_mode), MODE_INT, 0);
|
||||
if (imode == BLKmode)
|
||||
break;
|
||||
|
||||
compute_mode = imode;
|
||||
inner = gen_lowpart_for_combine (imode, inner);
|
||||
}
|
||||
|
||||
/* Compute a mask of LEN bits, if we can do this on the host machine. */
|
||||
if (len < HOST_BITS_PER_WIDE_INT)
|
||||
mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
|
||||
@ -5588,8 +5597,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
|
||||
|
||||
new = gen_rtx_MEM (tmode, plus_constant (XEXP (inner, 0), offset));
|
||||
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (inner);
|
||||
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (inner);
|
||||
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (inner);
|
||||
MEM_COPY_ATTRIBUTES (new, inner);
|
||||
}
|
||||
else if (GET_CODE (inner) == REG)
|
||||
{
|
||||
@ -5653,27 +5661,45 @@ make_extraction (mode, inner, pos, pos_rtx, len,
|
||||
#ifdef HAVE_insv
|
||||
if (in_dest)
|
||||
{
|
||||
wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_insv][0];
|
||||
pos_mode = insn_operand_mode[(int) CODE_FOR_insv][2];
|
||||
extraction_mode = insn_operand_mode[(int) CODE_FOR_insv][3];
|
||||
wanted_inner_reg_mode
|
||||
= (insn_operand_mode[(int) CODE_FOR_insv][0] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_insv][0]);
|
||||
pos_mode = (insn_operand_mode[(int) CODE_FOR_insv][2] == VOIDmode
|
||||
? word_mode : insn_operand_mode[(int) CODE_FOR_insv][2]);
|
||||
extraction_mode = (insn_operand_mode[(int) CODE_FOR_insv][3] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_insv][3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_extzv
|
||||
if (! in_dest && unsignedp)
|
||||
{
|
||||
wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
|
||||
pos_mode = insn_operand_mode[(int) CODE_FOR_extzv][3];
|
||||
extraction_mode = insn_operand_mode[(int) CODE_FOR_extzv][0];
|
||||
wanted_inner_reg_mode
|
||||
= (insn_operand_mode[(int) CODE_FOR_extzv][1] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_extzv][1]);
|
||||
pos_mode = (insn_operand_mode[(int) CODE_FOR_extzv][3] == VOIDmode
|
||||
? word_mode : insn_operand_mode[(int) CODE_FOR_extzv][3]);
|
||||
extraction_mode = (insn_operand_mode[(int) CODE_FOR_extzv][0] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_extzv][0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_extv
|
||||
if (! in_dest && ! unsignedp)
|
||||
{
|
||||
wanted_inner_reg_mode = insn_operand_mode[(int) CODE_FOR_extv][1];
|
||||
pos_mode = insn_operand_mode[(int) CODE_FOR_extv][3];
|
||||
extraction_mode = insn_operand_mode[(int) CODE_FOR_extv][0];
|
||||
wanted_inner_reg_mode
|
||||
= (insn_operand_mode[(int) CODE_FOR_extv][1] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_extv][1]);
|
||||
pos_mode = (insn_operand_mode[(int) CODE_FOR_extv][3] == VOIDmode
|
||||
? word_mode : insn_operand_mode[(int) CODE_FOR_extv][3]);
|
||||
extraction_mode = (insn_operand_mode[(int) CODE_FOR_extv][0] == VOIDmode
|
||||
? word_mode
|
||||
: insn_operand_mode[(int) CODE_FOR_extv][0]);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -5763,8 +5789,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
|
||||
rtx newmem = gen_rtx_MEM (wanted_inner_mode,
|
||||
plus_constant (XEXP (inner, 0), offset));
|
||||
RTX_UNCHANGING_P (newmem) = RTX_UNCHANGING_P (inner);
|
||||
MEM_VOLATILE_P (newmem) = MEM_VOLATILE_P (inner);
|
||||
MEM_IN_STRUCT_P (newmem) = MEM_IN_STRUCT_P (inner);
|
||||
MEM_COPY_ATTRIBUTES (newmem, inner);
|
||||
inner = newmem;
|
||||
}
|
||||
}
|
||||
@ -6328,7 +6353,7 @@ force_to_mode (x, mode, mask, reg, just_select)
|
||||
need it. */
|
||||
|
||||
if (GET_CODE (x) == AND && GET_CODE (XEXP (x, 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (x, 1)) == mask)
|
||||
&& (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) == mask)
|
||||
x = XEXP (x, 0);
|
||||
|
||||
/* If it remains an AND, try making another AND with the bits
|
||||
@ -6390,20 +6415,21 @@ force_to_mode (x, mode, mask, reg, just_select)
|
||||
unsigned HOST_WIDE_INT sp_mask = GET_MODE_MASK (mode);
|
||||
|
||||
sp_mask &= ~ (sp_alignment - 1);
|
||||
if ((sp_mask & ~ mask) == 0
|
||||
&& ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ mask) != 0)
|
||||
if ((sp_mask & ~ smask) == 0
|
||||
&& ((INTVAL (XEXP (x, 1)) - STACK_BIAS) & ~ smask) != 0)
|
||||
return force_to_mode (plus_constant (XEXP (x, 0),
|
||||
((INTVAL (XEXP (x, 1)) -
|
||||
STACK_BIAS) & mask)
|
||||
STACK_BIAS) & smask)
|
||||
+ STACK_BIAS),
|
||||
mode, mask, reg, next_select);
|
||||
mode, smask, reg, next_select);
|
||||
}
|
||||
#endif
|
||||
if ((nonzero_bits (XEXP (x, 0), mode) & ~ mask) == 0
|
||||
&& (INTVAL (XEXP (x, 1)) & ~ mask) != 0)
|
||||
if ((nonzero_bits (XEXP (x, 0), mode) & ~ smask) == 0
|
||||
&& (INTVAL (XEXP (x, 1)) & ~ smask) != 0)
|
||||
return force_to_mode (plus_constant (XEXP (x, 0),
|
||||
INTVAL (XEXP (x, 1)) & mask),
|
||||
mode, mask, reg, next_select);
|
||||
(INTVAL (XEXP (x, 1))
|
||||
& smask)),
|
||||
mode, smask, reg, next_select);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6549,7 +6575,7 @@ force_to_mode (x, mode, mask, reg, just_select)
|
||||
/* If we are just looking for the sign bit, we don't need this shift at
|
||||
all, even if it has a variable count. */
|
||||
if (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
|
||||
&& (mask == ((HOST_WIDE_INT) 1
|
||||
&& (mask == ((unsigned HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (GET_MODE (x)) - 1))))
|
||||
return force_to_mode (XEXP (x, 0), mode, mask, reg, next_select);
|
||||
|
||||
@ -7376,7 +7402,7 @@ simplify_and_const_int (x, mode, varop, constop)
|
||||
else
|
||||
{
|
||||
if (GET_CODE (XEXP (x, 1)) != CONST_INT
|
||||
|| INTVAL (XEXP (x, 1)) != constop)
|
||||
|| (unsigned HOST_WIDE_INT) INTVAL (XEXP (x, 1)) != constop)
|
||||
SUBST (XEXP (x, 1), GEN_INT (constop));
|
||||
|
||||
SUBST (XEXP (x, 0), varop);
|
||||
@ -8292,7 +8318,8 @@ merge_outer_ops (pop0, pconst0, op1, const1, mode, pcomp_p)
|
||||
op0 = NIL;
|
||||
else if (const0 == 0 && op0 == AND)
|
||||
op0 = SET;
|
||||
else if (const0 == GET_MODE_MASK (mode) && op0 == AND)
|
||||
else if ((unsigned HOST_WIDE_INT) const0 == GET_MODE_MASK (mode)
|
||||
&& op0 == AND)
|
||||
op0 = NIL;
|
||||
|
||||
/* If this would be an entire word for the target, but is not for
|
||||
@ -8475,8 +8502,7 @@ simplify_shift_const (x, code, result_mode, varop, count)
|
||||
plus_constant (XEXP (varop, 0),
|
||||
count / BITS_PER_UNIT));
|
||||
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (varop);
|
||||
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (varop);
|
||||
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (varop);
|
||||
MEM_COPY_ATTRIBUTES (new, varop);
|
||||
varop = gen_rtx_combine (code == ASHIFTRT ? SIGN_EXTEND
|
||||
: ZERO_EXTEND, mode, new);
|
||||
count = 0;
|
||||
@ -9066,18 +9092,14 @@ simplify_shift_const (x, code, result_mode, varop, count)
|
||||
PNOTES is a pointer to a location where any REG_UNUSED notes added for
|
||||
the CLOBBERs are placed.
|
||||
|
||||
PADDED_SCRATCHES is set to the number of (clobber (scratch)) patterns
|
||||
we had to add.
|
||||
|
||||
The value is the final insn code from the pattern ultimately matched,
|
||||
or -1. */
|
||||
|
||||
static int
|
||||
recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
|
||||
recog_for_combine (pnewpat, insn, pnotes)
|
||||
rtx *pnewpat;
|
||||
rtx insn;
|
||||
rtx *pnotes;
|
||||
int *padded_scratches;
|
||||
{
|
||||
register rtx pat = *pnewpat;
|
||||
int insn_code_number;
|
||||
@ -9085,8 +9107,6 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
|
||||
int i;
|
||||
rtx notes = 0;
|
||||
|
||||
*padded_scratches = 0;
|
||||
|
||||
/* If PAT is a PARALLEL, check to see if it contains the CLOBBER
|
||||
we use to indicate that something didn't match. If we find such a
|
||||
thing, force rejection. */
|
||||
@ -9148,8 +9168,6 @@ recog_for_combine (pnewpat, insn, pnotes, padded_scratches)
|
||||
if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == REG
|
||||
&& ! reg_dead_at_p (XEXP (XVECEXP (newpat, 0, i), 0), insn))
|
||||
return -1;
|
||||
else if (GET_CODE (XEXP (XVECEXP (newpat, 0, i), 0)) == SCRATCH)
|
||||
(*padded_scratches)++;
|
||||
notes = gen_rtx_EXPR_LIST (REG_UNUSED,
|
||||
XEXP (XVECEXP (newpat, 0, i), 0), notes);
|
||||
}
|
||||
@ -9243,8 +9261,7 @@ gen_lowpart_for_combine (mode, x)
|
||||
}
|
||||
new = gen_rtx_MEM (mode, plus_constant (XEXP (x, 0), offset));
|
||||
RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
|
||||
MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
|
||||
MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
|
||||
MEM_COPY_ATTRIBUTES (new, x);
|
||||
return new;
|
||||
}
|
||||
|
||||
@ -9279,7 +9296,7 @@ gen_lowpart_for_combine (mode, x)
|
||||
static rtx
|
||||
gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
enum rtx_code code;
|
||||
enum machine_mode mode;
|
||||
#endif
|
||||
@ -9293,7 +9310,7 @@ gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
|
||||
|
||||
VA_START (p, mode);
|
||||
|
||||
#ifndef __STDC__
|
||||
#ifndef ANSI_PROTOTYPES
|
||||
code = va_arg (p, enum rtx_code);
|
||||
mode = va_arg (p, enum machine_mode);
|
||||
#endif
|
||||
@ -9553,7 +9570,7 @@ simplify_comparison (code, pop0, pop1)
|
||||
for (tmode = GET_CLASS_NARROWEST_MODE
|
||||
(GET_MODE_CLASS (GET_MODE (op0)));
|
||||
tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
|
||||
if (c0 == GET_MODE_MASK (tmode))
|
||||
if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
|
||||
{
|
||||
op0 = gen_lowpart_for_combine (tmode, inner_op0);
|
||||
op1 = gen_lowpart_for_combine (tmode, inner_op1);
|
||||
@ -9628,7 +9645,7 @@ simplify_comparison (code, pop0, pop1)
|
||||
|| code == LT || code == LTU)
|
||||
&& mode_width <= HOST_BITS_PER_WIDE_INT
|
||||
&& exact_log2 (const_op) >= 0
|
||||
&& nonzero_bits (op0, mode) == const_op)
|
||||
&& nonzero_bits (op0, mode) == (unsigned HOST_WIDE_INT) const_op)
|
||||
{
|
||||
code = (code == EQ || code == GE || code == GEU ? NE : EQ);
|
||||
op1 = const0_rtx, const_op = 0;
|
||||
@ -9820,12 +9837,16 @@ simplify_comparison (code, pop0, pop1)
|
||||
&& (i = exact_log2 (INTVAL (XEXP (op0, 0)))) >= 0)
|
||||
{
|
||||
if (BITS_BIG_ENDIAN)
|
||||
{
|
||||
#ifdef HAVE_extzv
|
||||
i = (GET_MODE_BITSIZE
|
||||
(insn_operand_mode[(int) CODE_FOR_extzv][1]) - 1 - i);
|
||||
mode = insn_operand_mode[(int) CODE_FOR_extzv][1];
|
||||
if (mode == VOIDmode)
|
||||
mode = word_mode;
|
||||
i = (GET_MODE_BITSIZE (mode) - 1 - i);
|
||||
#else
|
||||
i = BITS_PER_WORD - 1 - i;
|
||||
i = BITS_PER_WORD - 1 - i;
|
||||
#endif
|
||||
}
|
||||
|
||||
op0 = XEXP (op0, 2);
|
||||
op1 = GEN_INT (i);
|
||||
@ -9953,7 +9974,7 @@ simplify_comparison (code, pop0, pop1)
|
||||
&& (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0)))
|
||||
<= HOST_BITS_PER_WIDE_INT)
|
||||
&& ((unsigned HOST_WIDE_INT) const_op
|
||||
< (((HOST_WIDE_INT) 1
|
||||
< (((unsigned HOST_WIDE_INT) 1
|
||||
<< (GET_MODE_BITSIZE (GET_MODE (XEXP (op0, 0))) - 1)))))
|
||||
{
|
||||
op0 = XEXP (op0, 0);
|
||||
@ -9977,7 +9998,7 @@ simplify_comparison (code, pop0, pop1)
|
||||
&& GET_CODE (XEXP (SUBREG_REG (op0), 1)) == CONST_INT
|
||||
&& INTVAL (XEXP (SUBREG_REG (op0), 1)) < 0
|
||||
&& (- INTVAL (XEXP (SUBREG_REG (op0), 1))
|
||||
< GET_MODE_MASK (mode) / 2)
|
||||
< (HOST_WIDE_INT)(GET_MODE_MASK (mode) / 2))
|
||||
&& (unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode) / 2
|
||||
&& (0 == (nonzero_bits (XEXP (SUBREG_REG (op0), 0),
|
||||
GET_MODE (SUBREG_REG (op0)))
|
||||
@ -10181,7 +10202,7 @@ simplify_comparison (code, pop0, pop1)
|
||||
&& GET_CODE (XEXP (op0, 1)) == CONST_INT
|
||||
&& mode_width <= HOST_BITS_PER_WIDE_INT
|
||||
&& ((INTVAL (XEXP (op0, 1)) & GET_MODE_MASK (mode))
|
||||
== (HOST_WIDE_INT) 1 << (mode_width - 1)))
|
||||
== (unsigned HOST_WIDE_INT) 1 << (mode_width - 1)))
|
||||
{
|
||||
op0 = XEXP (op0, 0);
|
||||
code = (code == EQ ? GE : LT);
|
||||
@ -10232,8 +10253,8 @@ simplify_comparison (code, pop0, pop1)
|
||||
&& (INTVAL (XEXP (op0, 1)) & ~ mask) == 0
|
||||
&& 0 == (~ GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))
|
||||
& INTVAL (XEXP (op0, 1)))
|
||||
&& INTVAL (XEXP (op0, 1)) != mask
|
||||
&& (INTVAL (XEXP (op0, 1))
|
||||
&& (unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1)) != mask
|
||||
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op0, 1))
|
||||
!= GET_MODE_MASK (GET_MODE (SUBREG_REG (XEXP (op0, 0))))))
|
||||
|
||||
{
|
||||
@ -11012,7 +11033,7 @@ reg_dead_at_p (reg, insn)
|
||||
else
|
||||
{
|
||||
for (block = 0; block < n_basic_blocks; block++)
|
||||
if (insn == basic_block_head[block])
|
||||
if (insn == BLOCK_HEAD (block))
|
||||
break;
|
||||
|
||||
if (block == n_basic_blocks)
|
||||
@ -11020,7 +11041,7 @@ reg_dead_at_p (reg, insn)
|
||||
}
|
||||
|
||||
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[block], i))
|
||||
if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
@ -11413,6 +11434,17 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
place = i3;
|
||||
break;
|
||||
|
||||
case REG_EH_REGION:
|
||||
/* This note must remain with the call. It should not be possible
|
||||
for both I2 and I3 to be a call. */
|
||||
if (GET_CODE (i3) == CALL_INSN)
|
||||
place = i3;
|
||||
else if (i2 && GET_CODE (i2) == CALL_INSN)
|
||||
place = i2;
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case REG_UNUSED:
|
||||
/* Any clobbers for i3 may still exist, and so we must process
|
||||
REG_UNUSED notes from that insn.
|
||||
@ -11476,7 +11508,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
|
||||
case REG_INC:
|
||||
case REG_NO_CONFLICT:
|
||||
case REG_LABEL:
|
||||
/* These notes say something about how a register is used. They must
|
||||
be present on any use of the register in I2 or I3. */
|
||||
if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3)))
|
||||
@ -11491,6 +11522,30 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_LABEL:
|
||||
/* This can show up in several ways -- either directly in the
|
||||
pattern, or hidden off in the constant pool with (or without?)
|
||||
a REG_EQUAL note. */
|
||||
/* ??? Ignore the without-reg_equal-note problem for now. */
|
||||
if (reg_mentioned_p (XEXP (note, 0), PATTERN (i3))
|
||||
|| ((tem = find_reg_note (i3, REG_EQUAL, NULL_RTX))
|
||||
&& GET_CODE (XEXP (tem, 0)) == LABEL_REF
|
||||
&& XEXP (XEXP (tem, 0), 0) == XEXP (note, 0)))
|
||||
place = i3;
|
||||
|
||||
if (i2
|
||||
&& (reg_mentioned_p (XEXP (note, 0), PATTERN (i2))
|
||||
|| ((tem = find_reg_note (i2, REG_EQUAL, NULL_RTX))
|
||||
&& GET_CODE (XEXP (tem, 0)) == LABEL_REF
|
||||
&& XEXP (XEXP (tem, 0), 0) == XEXP (note, 0))))
|
||||
{
|
||||
if (place)
|
||||
place2 = i2;
|
||||
else
|
||||
place = i2;
|
||||
}
|
||||
break;
|
||||
|
||||
case REG_WAS_0:
|
||||
/* It is too much trouble to try to see if this note is still
|
||||
correct in all situations. It is better to simply delete it. */
|
||||
@ -11578,6 +11633,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
{
|
||||
rtx set = single_set (tem);
|
||||
rtx inner_dest = 0;
|
||||
#ifdef HAVE_cc0
|
||||
rtx cc0_setter = NULL_RTX;
|
||||
#endif
|
||||
|
||||
if (set != 0)
|
||||
for (inner_dest = SET_DEST (set);
|
||||
@ -11588,10 +11646,21 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
;
|
||||
|
||||
/* Verify that it was the set, and not a clobber that
|
||||
modified the register. */
|
||||
modified the register.
|
||||
|
||||
CC0 targets must be careful to maintain setter/user
|
||||
pairs. If we cannot delete the setter due to side
|
||||
effects, mark the user with an UNUSED note instead
|
||||
of deleting it. */
|
||||
|
||||
if (set != 0 && ! side_effects_p (SET_SRC (set))
|
||||
&& rtx_equal_p (XEXP (note, 0), inner_dest))
|
||||
&& rtx_equal_p (XEXP (note, 0), inner_dest)
|
||||
#ifdef HAVE_cc0
|
||||
&& (! reg_mentioned_p (cc0_rtx, SET_SRC (set))
|
||||
|| ((cc0_setter = prev_cc0_setter (tem)) != NULL
|
||||
&& sets_cc0_p (PATTERN (cc0_setter)) > 0))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
/* Move the notes and links of TEM elsewhere.
|
||||
This might delete other dead insns recursively.
|
||||
@ -11607,6 +11676,23 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
PUT_CODE (tem, NOTE);
|
||||
NOTE_LINE_NUMBER (tem) = NOTE_INSN_DELETED;
|
||||
NOTE_SOURCE_FILE (tem) = 0;
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
/* Delete the setter too. */
|
||||
if (cc0_setter)
|
||||
{
|
||||
PATTERN (cc0_setter) = pc_rtx;
|
||||
|
||||
distribute_notes (REG_NOTES (cc0_setter),
|
||||
cc0_setter, cc0_setter,
|
||||
NULL_RTX, NULL_RTX, NULL_RTX);
|
||||
distribute_links (LOG_LINKS (cc0_setter));
|
||||
|
||||
PUT_CODE (cc0_setter, NOTE);
|
||||
NOTE_LINE_NUMBER (cc0_setter) = NOTE_INSN_DELETED;
|
||||
NOTE_SOURCE_FILE (cc0_setter) = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* If the register is both set and used here, put the
|
||||
REG_DEAD note here, but place a REG_UNUSED note
|
||||
@ -11672,9 +11758,9 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
|
||||
tem);
|
||||
|
||||
/* If this insn was emitted between blocks, then update
|
||||
basic_block_head of the current block to include it. */
|
||||
if (basic_block_end[this_basic_block - 1] == tem)
|
||||
basic_block_head[this_basic_block] = place;
|
||||
BLOCK_HEAD of the current block to include it. */
|
||||
if (BLOCK_END (this_basic_block - 1) == tem)
|
||||
BLOCK_HEAD (this_basic_block) = place;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11873,7 +11959,7 @@ distribute_links (links)
|
||||
|
||||
for (insn = NEXT_INSN (XEXP (link, 0));
|
||||
(insn && (this_basic_block == n_basic_blocks - 1
|
||||
|| basic_block_head[this_basic_block + 1] != insn));
|
||||
|| BLOCK_HEAD (this_basic_block + 1) != insn));
|
||||
insn = NEXT_INSN (insn))
|
||||
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||
&& reg_overlap_mentioned_p (reg, PATTERN (insn)))
|
||||
@ -11935,7 +12021,7 @@ void
|
||||
dump_combine_stats (file)
|
||||
FILE *file;
|
||||
{
|
||||
fprintf
|
||||
fnotice
|
||||
(file,
|
||||
";; Combiner statistics: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n\n",
|
||||
combine_attempts, combine_merges, combine_extras, combine_successes);
|
||||
@ -11945,7 +12031,7 @@ void
|
||||
dump_combine_total_stats (file)
|
||||
FILE *file;
|
||||
{
|
||||
fprintf
|
||||
fnotice
|
||||
(file,
|
||||
"\n;; Combiner totals: %d attempts, %d substitutions (%d requiring new space),\n;; %d successes.\n",
|
||||
total_attempts, total_merges, total_extras, total_successes);
|
||||
|
@ -1,10 +1,22 @@
|
||||
/* config.in. Generated automatically from configure.in by autoheader. */
|
||||
/* Define if you can safely include both <string.h> and <strings.h>. */
|
||||
#undef STRING_WITH_STRINGS
|
||||
|
||||
/* Define if printf supports "%p". */
|
||||
#undef HAVE_PRINTF_PTR
|
||||
|
||||
/* Define if you want expensive run-time checks. */
|
||||
#undef ENABLE_CHECKING
|
||||
|
||||
/* Define to 1 if NLS is requested. */
|
||||
#undef ENABLE_NLS
|
||||
|
||||
/* Define as 1 if you have catgets and don't want to use GNU gettext. */
|
||||
#undef HAVE_CATGETS
|
||||
|
||||
/* Define as 1 if you have gettext and don't want to use GNU gettext. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define if your cpp understands the stringify operator. */
|
||||
#undef HAVE_CPP_STRINGIFY
|
||||
|
||||
@ -18,9 +30,22 @@
|
||||
/* Define if your assembler supports .balign and .p2align. */
|
||||
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
|
||||
|
||||
/* Define if your assembler supports .subsection and .subsection -1 starts
|
||||
emitting at the beginning of your section */
|
||||
#undef HAVE_GAS_SUBSECTION_ORDERING
|
||||
|
||||
/* Define if your assembler uses the old HImode fild and fist notation. */
|
||||
#undef HAVE_GAS_FILDS_FISTS
|
||||
|
||||
/* Define if you have a working <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define if your locale.h file contains LC_MESSAGES. */
|
||||
#undef HAVE_LC_MESSAGES
|
||||
|
||||
/* Define as 1 if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Whether malloc must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_MALLOC
|
||||
|
||||
@ -54,6 +79,9 @@
|
||||
/* Whether atol must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_ATOL
|
||||
|
||||
/* Whether atof must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_ATOF
|
||||
|
||||
/* Whether sbrk must be declared even if <stdlib.h> is included. */
|
||||
#undef NEED_DECLARATION_SBRK
|
||||
|
||||
@ -63,6 +91,12 @@
|
||||
/* Whether strerror must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRERROR
|
||||
|
||||
/* Whether strsignal must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRSIGNAL
|
||||
|
||||
/* Whether strstr must be declared even if <string.h> is included. */
|
||||
#undef NEED_DECLARATION_STRSTR
|
||||
|
||||
/* Whether getcwd must be declared even if <unistd.h> is included. */
|
||||
#undef NEED_DECLARATION_GETCWD
|
||||
|
||||
@ -75,15 +109,79 @@
|
||||
/* Whether setrlimit must be declared even if <sys/resource.h> is included. */
|
||||
#undef NEED_DECLARATION_SETRLIMIT
|
||||
|
||||
/* Define if you want expensive run-time checks. */
|
||||
#undef ENABLE_CHECKING
|
||||
/* Whether putc_unlocked must be declared even if <stdio.h> is included. */
|
||||
#undef NEED_DECLARATION_PUTC_UNLOCKED
|
||||
|
||||
/* Whether fputs_unlocked must be declared even if <stdio.h> is included. */
|
||||
#undef NEED_DECLARATION_FPUTS_UNLOCKED
|
||||
|
||||
/* Define to enable the use of a default assembler. */
|
||||
#undef DEFAULT_ASSEMBLER
|
||||
|
||||
/* Define to enable the use of a default linker. */
|
||||
#undef DEFAULT_LINKER
|
||||
|
||||
/* Define if host mkdir takes a single argument. */
|
||||
#undef MKDIR_TAKES_ONE_ARG
|
||||
|
||||
/* Define to the name of the distribution. */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the version of the distribution. */
|
||||
#undef VERSION
|
||||
|
||||
/* Define if using alloca.c. */
|
||||
#undef C_ALLOCA
|
||||
|
||||
/* Define to empty if the keyword does not work. */
|
||||
#undef const
|
||||
|
||||
/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
|
||||
This function is required for alloca.c support on those systems. */
|
||||
#undef CRAY_STACKSEG_END
|
||||
|
||||
/* Define if you have alloca, as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
|
||||
/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
|
||||
#undef HAVE_ALLOCA_H
|
||||
|
||||
/* Define if you don't have vprintf but do have _doprnt. */
|
||||
#undef HAVE_DOPRNT
|
||||
|
||||
/* Define if you have a working `mmap' system call. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define if you have <vfork.h>. */
|
||||
#undef HAVE_VFORK_H
|
||||
|
||||
/* Define if you have the vprintf function. */
|
||||
#undef HAVE_VPRINTF
|
||||
|
||||
/* Define as __inline if that's what the C compiler calls it. */
|
||||
#undef inline
|
||||
|
||||
/* Define to `long' if <sys/types.h> doesn't define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> doesn't define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to `unsigned' if <sys/types.h> doesn't define. */
|
||||
#undef size_t
|
||||
|
||||
/* If using the C implementation of alloca, define if you know the
|
||||
direction of stack growth for your system; otherwise it will be
|
||||
automatically deduced at run-time.
|
||||
STACK_DIRECTION > 0 => grows toward higher addresses
|
||||
STACK_DIRECTION < 0 => grows toward lower addresses
|
||||
STACK_DIRECTION = 0 => direction of growth unknown
|
||||
*/
|
||||
#undef STACK_DIRECTION
|
||||
|
||||
/* Define if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
@ -93,6 +191,18 @@
|
||||
/* Define if you can safely include both <sys/time.h> and <time.h>. */
|
||||
#undef TIME_WITH_SYS_TIME
|
||||
|
||||
/* Define vfork as fork if vfork does not work. */
|
||||
#undef vfork
|
||||
|
||||
/* Define if you have the __argz_count function. */
|
||||
#undef HAVE___ARGZ_COUNT
|
||||
|
||||
/* Define if you have the __argz_next function. */
|
||||
#undef HAVE___ARGZ_NEXT
|
||||
|
||||
/* Define if you have the __argz_stringify function. */
|
||||
#undef HAVE___ARGZ_STRINGIFY
|
||||
|
||||
/* Define if you have the atoll function. */
|
||||
#undef HAVE_ATOLL
|
||||
|
||||
@ -111,6 +221,21 @@
|
||||
/* Define if you have the bzero function. */
|
||||
#undef HAVE_BZERO
|
||||
|
||||
/* Define if you have the dcgettext function. */
|
||||
#undef HAVE_DCGETTEXT
|
||||
|
||||
/* Define if you have the fputc_unlocked function. */
|
||||
#undef HAVE_FPUTC_UNLOCKED
|
||||
|
||||
/* Define if you have the fputs_unlocked function. */
|
||||
#undef HAVE_FPUTS_UNLOCKED
|
||||
|
||||
/* Define if you have the getcwd function. */
|
||||
#undef HAVE_GETCWD
|
||||
|
||||
/* Define if you have the getpagesize function. */
|
||||
#undef HAVE_GETPAGESIZE
|
||||
|
||||
/* Define if you have the getrlimit function. */
|
||||
#undef HAVE_GETRLIMIT
|
||||
|
||||
@ -126,39 +251,78 @@
|
||||
/* Define if you have the kill function. */
|
||||
#undef HAVE_KILL
|
||||
|
||||
/* Define if you have the munmap function. */
|
||||
#undef HAVE_MUNMAP
|
||||
|
||||
/* Define if you have the popen function. */
|
||||
#undef HAVE_POPEN
|
||||
|
||||
/* Define if you have the putc_unlocked function. */
|
||||
#undef HAVE_PUTC_UNLOCKED
|
||||
|
||||
/* Define if you have the putenv function. */
|
||||
#undef HAVE_PUTENV
|
||||
|
||||
/* Define if you have the rindex function. */
|
||||
#undef HAVE_RINDEX
|
||||
|
||||
/* Define if you have the setenv function. */
|
||||
#undef HAVE_SETENV
|
||||
|
||||
/* Define if you have the setlocale function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define if you have the setrlimit function. */
|
||||
#undef HAVE_SETRLIMIT
|
||||
|
||||
/* Define if you have the stpcpy function. */
|
||||
#undef HAVE_STPCPY
|
||||
|
||||
/* Define if you have the strcasecmp function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define if you have the strchr function. */
|
||||
#undef HAVE_STRCHR
|
||||
|
||||
/* Define if you have the strdup function. */
|
||||
#undef HAVE_STRDUP
|
||||
|
||||
/* Define if you have the strerror function. */
|
||||
#undef HAVE_STRERROR
|
||||
|
||||
/* Define if you have the strrchr function. */
|
||||
#undef HAVE_STRRCHR
|
||||
|
||||
/* Define if you have the strsignal function. */
|
||||
#undef HAVE_STRSIGNAL
|
||||
|
||||
/* Define if you have the strtoul function. */
|
||||
#undef HAVE_STRTOUL
|
||||
|
||||
/* Define if you have the sysconf function. */
|
||||
#undef HAVE_SYSCONF
|
||||
|
||||
/* Define if you have the <argz.h> header file. */
|
||||
#undef HAVE_ARGZ_H
|
||||
|
||||
/* Define if you have the <direct.h> header file. */
|
||||
#undef HAVE_DIRECT_H
|
||||
|
||||
/* Define if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define if you have the <limits.h> header file. */
|
||||
#undef HAVE_LIMITS_H
|
||||
|
||||
/* Define if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define if you have the <malloc.h> header file. */
|
||||
#undef HAVE_MALLOC_H
|
||||
|
||||
/* Define if you have the <nl_types.h> header file. */
|
||||
#undef HAVE_NL_TYPES_H
|
||||
|
||||
/* Define if you have the <stab.h> header file. */
|
||||
#undef HAVE_STAB_H
|
||||
|
||||
@ -183,20 +347,20 @@
|
||||
/* Define if you have the <sys/resource.h> header file. */
|
||||
#undef HAVE_SYS_RESOURCE_H
|
||||
|
||||
/* Define if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define if you have the <sys/times.h> header file. */
|
||||
#undef HAVE_SYS_TIMES_H
|
||||
|
||||
/* Define if you have the <sys/wait.h> header file. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define if you have the <time.h> header file. */
|
||||
#undef HAVE_TIME_H
|
||||
|
||||
/* Define if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define if you have the <wait.h> header file. */
|
||||
#undef HAVE_WAIT_H
|
||||
/* Define if you have the i library (-li). */
|
||||
#undef HAVE_LIBI
|
||||
|
252
contrib/gcc/config/alpha/alpha-interix.h
Normal file
252
contrib/gcc/config/alpha/alpha-interix.h
Normal file
@ -0,0 +1,252 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha
|
||||
running Windows/NT.
|
||||
Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
|
||||
Donn Terry, Softway Systems, Inc.
|
||||
From code
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
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. */
|
||||
|
||||
/* cpp handles __STDC__ */
|
||||
/* The three "Alpha" defines on the first such line are from the CLAXP spec */
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES " \
|
||||
-D__INTERIX \
|
||||
-D__OPENNT \
|
||||
-D__Alpha_AXP -D_M_ALPHA -D_ALPHA_ \
|
||||
-D__alpha -D__alpha__\
|
||||
-D__stdcall= \
|
||||
-D__cdecl= \
|
||||
-Asystem(unix) -Asystem(interix) -Asystem(interix) -Acpu(alpha) -Amachine(alpha)"
|
||||
|
||||
#undef CPP_SUBTARGET_SPEC
|
||||
#define CPP_SUBTARGET_SPEC "\
|
||||
-remap \
|
||||
%{posix:-D_POSIX_SOURCE} \
|
||||
-idirafter %$INTERIX_ROOT/usr/include"
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (alpha Interix)");
|
||||
|
||||
/* alpha.h sets this, but it doesn't apply to us */
|
||||
#undef OBJECT_FORMAT_ECOFF
|
||||
#undef OBJECT_FORMAT_COFF
|
||||
|
||||
/* LINK_SPEC */
|
||||
|
||||
/* MD_STARTFILE_PREFIX */
|
||||
|
||||
/* ASM_OUTPUT_LOOP_ALIGN; ASM_OUTPUT_ALIGN_CODE */
|
||||
|
||||
/* Codegen macro overrides for NT internal conventions */
|
||||
|
||||
/* the below are ecoff specific... we don't need them, so
|
||||
undef them (they'll get a default later) */
|
||||
|
||||
#undef PUT_SDB_BLOCK_START
|
||||
#undef PUT_SDB_BLOCK_END
|
||||
|
||||
/* the following are OSF linker (not gld) specific... we don't want them */
|
||||
#undef HAS_INIT_SECTION
|
||||
#undef LD_INIT_SWITCH
|
||||
#undef LD_FINI_SWITCH
|
||||
|
||||
|
||||
/* The following are needed for C++, but also needed for profiling */
|
||||
|
||||
/* Support const sections and the ctors and dtors sections for g++.
|
||||
Note that there appears to be two different ways to support const
|
||||
sections at the moment. You can either #define the symbol
|
||||
READONLY_DATA_SECTION (giving it some code which switches to the
|
||||
readonly data section) or else you can #define the symbols
|
||||
EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
|
||||
SELECT_RTX_SECTION. We do both here just to be on the safe side. */
|
||||
|
||||
#define USE_CONST_SECTION 1
|
||||
|
||||
#define CONST_SECTION_ASM_OP ".rdata"
|
||||
|
||||
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
|
||||
|
||||
Note that we want to give these sections the SHF_WRITE attribute
|
||||
because these sections will actually contain data (i.e. tables of
|
||||
addresses of functions in the current root executable or shared library
|
||||
file) and, in the case of a shared library, the relocatable addresses
|
||||
will have to be properly resolved/relocated (and then written into) by
|
||||
the dynamic linker when it actually attaches the given shared library
|
||||
to the executing process. (Note that on SVR4, you may wish to use the
|
||||
`-z text' option to the ELF linker, when building a shared library, as
|
||||
an additional check that you are doing everything right. But if you do
|
||||
use the `-z text' option when building a shared library, you will get
|
||||
errors unless the .ctors and .dtors sections are marked as writable
|
||||
via the SHF_WRITE attribute.) */
|
||||
|
||||
#define CTORS_SECTION_ASM_OP ".ctors"
|
||||
#define DTORS_SECTION_ASM_OP ".dtors"
|
||||
|
||||
/* A default list of other sections which we might be "in" at any given
|
||||
time. For targets that use additional sections (e.g. .tdesc) you
|
||||
should override this definition in the target-specific file which
|
||||
includes this file. */
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
|
||||
|
||||
/* A default list of extra section function definitions. For targets
|
||||
that use additional sections (e.g. .tdesc) you should override this
|
||||
definition in the target-specific file which includes this file. */
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CONST_SECTION_FUNCTION \
|
||||
CTORS_SECTION_FUNCTION \
|
||||
DTORS_SECTION_FUNCTION
|
||||
|
||||
#undef READONLY_DATA_SECTION
|
||||
#define READONLY_DATA_SECTION() const_section ()
|
||||
|
||||
extern void text_section ();
|
||||
|
||||
#define CONST_SECTION_FUNCTION \
|
||||
void \
|
||||
const_section () \
|
||||
{ \
|
||||
if (!USE_CONST_SECTION) \
|
||||
text_section(); \
|
||||
else if (in_section != in_const) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
|
||||
in_section = in_const; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
ctors_section () \
|
||||
{ \
|
||||
if (in_section != in_ctors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
|
||||
in_section = in_ctors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
dtors_section () \
|
||||
{ \
|
||||
if (in_section != in_dtors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
|
||||
in_section = in_dtors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define INT_ASM_OP ".long"
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global constructors. */
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global destructors. */
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* The linker will take care of this, and having them causes problems with
|
||||
ld -r (specifically -rU). */
|
||||
#define CTOR_LISTS_DEFINED_EXTERNALLY 1
|
||||
|
||||
#define SET_ASM_OP ".set"
|
||||
/* Output a definition (implements alias) */
|
||||
#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
|
||||
do \
|
||||
{ \
|
||||
fprintf ((FILE), "\t"); \
|
||||
assemble_name (FILE, LABEL1); \
|
||||
fprintf (FILE, "="); \
|
||||
assemble_name (FILE, LABEL2); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* We use the defaults, so undef the null definitions */
|
||||
#undef PUT_SDB_FUNCTION_START
|
||||
#undef PUT_SDB_FUNCTION_END
|
||||
#undef PUT_SDB_EPILOGUE_END
|
||||
|
||||
#define HOST_PTR_PRINTF "%p"
|
||||
#define HOST_PTR_AS_INT unsigned long
|
||||
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
|
||||
#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
|
||||
|
||||
/* DWARF2 Unwinding doesn't work with exception handling yet. */
|
||||
#undef DWARF2_UNWIND_INFO
|
||||
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
/* The definition of this macro implies that there are cases where
|
||||
a scalar value cannot be returned in registers.
|
||||
|
||||
On NT (according to the spec) anything except strings/array that fits
|
||||
in 64 bits is returned in the registers (this appears to differ from
|
||||
the rest of the Alpha family). */
|
||||
|
||||
#undef RETURN_IN_MEMORY
|
||||
#define RETURN_IN_MEMORY(TYPE) \
|
||||
(TREE_CODE (TYPE) == ARRAY_TYPE || int_size_in_bytes(TYPE) > 8)
|
||||
|
||||
#define ASM_LOAD_ADDR(loc, reg) " lda " #reg "," #loc "\n"
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
{ \
|
||||
alpha_write_verstamp (FILE); \
|
||||
fprintf (FILE, "\t.set noreorder\n"); \
|
||||
fprintf (FILE, "\t.set volatile\n"); \
|
||||
fprintf (FILE, "\t.set noat\n"); \
|
||||
fprintf (FILE, "\t.globl\t__fltused\n"); \
|
||||
ASM_OUTPUT_SOURCE_FILENAME (FILE, main_input_filename); \
|
||||
}
|
||||
|
||||
/* The current Interix assembler (consistent with the DEC documentation)
|
||||
uses a=b NOT .set a,b; .set is for assembler options. */
|
||||
#undef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
|
||||
#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
|
||||
do { \
|
||||
assemble_name (FILE, SY); \
|
||||
fputc ('=', FILE); \
|
||||
assemble_name (FILE, HI); \
|
||||
fputc ('-', FILE); \
|
||||
assemble_name (FILE, LO); \
|
||||
} while (0)
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha.
|
||||
Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 93-98, 1999 Free Software Foundation, Inc.
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -95,73 +95,76 @@ extern enum alpha_fp_trap_mode alpha_fptm;
|
||||
|
||||
/* This means that floating-point support exists in the target implementation
|
||||
of the Alpha architecture. This is usually the default. */
|
||||
|
||||
#define MASK_FP 1
|
||||
#define MASK_FP (1 << 0)
|
||||
#define TARGET_FP (target_flags & MASK_FP)
|
||||
|
||||
/* This means that floating-point registers are allowed to be used. Note
|
||||
that Alpha implementations without FP operations are required to
|
||||
provide the FP registers. */
|
||||
|
||||
#define MASK_FPREGS 2
|
||||
#define MASK_FPREGS (1 << 1)
|
||||
#define TARGET_FPREGS (target_flags & MASK_FPREGS)
|
||||
|
||||
/* This means that gas is used to process the assembler file. */
|
||||
|
||||
#define MASK_GAS 4
|
||||
#define MASK_GAS (1 << 2)
|
||||
#define TARGET_GAS (target_flags & MASK_GAS)
|
||||
|
||||
/* This means that we should mark procedures as IEEE conformant. */
|
||||
|
||||
#define MASK_IEEE_CONFORMANT 8
|
||||
#define MASK_IEEE_CONFORMANT (1 << 3)
|
||||
#define TARGET_IEEE_CONFORMANT (target_flags & MASK_IEEE_CONFORMANT)
|
||||
|
||||
/* This means we should be IEEE-compliant except for inexact. */
|
||||
|
||||
#define MASK_IEEE 16
|
||||
#define MASK_IEEE (1 << 4)
|
||||
#define TARGET_IEEE (target_flags & MASK_IEEE)
|
||||
|
||||
/* This means we should be fully IEEE-compliant. */
|
||||
|
||||
#define MASK_IEEE_WITH_INEXACT 32
|
||||
#define MASK_IEEE_WITH_INEXACT (1 << 5)
|
||||
#define TARGET_IEEE_WITH_INEXACT (target_flags & MASK_IEEE_WITH_INEXACT)
|
||||
|
||||
/* This means we must construct all constants rather than emitting
|
||||
them as literal data. */
|
||||
|
||||
#define MASK_BUILD_CONSTANTS 128
|
||||
#define MASK_BUILD_CONSTANTS (1 << 6)
|
||||
#define TARGET_BUILD_CONSTANTS (target_flags & MASK_BUILD_CONSTANTS)
|
||||
|
||||
/* This means we handle floating points in VAX F- (float)
|
||||
or G- (double) Format. */
|
||||
|
||||
#define MASK_FLOAT_VAX 512
|
||||
#define MASK_FLOAT_VAX (1 << 7)
|
||||
#define TARGET_FLOAT_VAX (target_flags & MASK_FLOAT_VAX)
|
||||
|
||||
/* This means that the processor has byte and half word loads and stores
|
||||
(the BWX extension). */
|
||||
|
||||
#define MASK_BWX 1024
|
||||
#define MASK_BWX (1 << 8)
|
||||
#define TARGET_BWX (target_flags & MASK_BWX)
|
||||
|
||||
/* This means that the processor has the CIX extension. */
|
||||
#define MASK_CIX 2048
|
||||
#define TARGET_CIX (target_flags & MASK_CIX)
|
||||
|
||||
/* This means that the processor has the MAX extension. */
|
||||
#define MASK_MAX 4096
|
||||
#define MASK_MAX (1 << 9)
|
||||
#define TARGET_MAX (target_flags & MASK_MAX)
|
||||
|
||||
/* This means that the processor has the FIX extension. */
|
||||
#define MASK_FIX (1 << 10)
|
||||
#define TARGET_FIX (target_flags & MASK_FIX)
|
||||
|
||||
/* This means that the processor has the CIX extension. */
|
||||
#define MASK_CIX (1 << 11)
|
||||
#define TARGET_CIX (target_flags & MASK_CIX)
|
||||
|
||||
/* This means that the processor is an EV5, EV56, or PCA56. This is defined
|
||||
only in TARGET_CPU_DEFAULT. */
|
||||
#define MASK_CPU_EV5 8192
|
||||
#define MASK_CPU_EV5 (1 << 28)
|
||||
|
||||
/* Likewise for EV6. */
|
||||
#define MASK_CPU_EV6 16384
|
||||
#define MASK_CPU_EV6 (1 << 29)
|
||||
|
||||
/* This means we support the .arch directive in the assembler. Only
|
||||
defined in TARGET_CPU_DEFAULT. */
|
||||
#define MASK_SUPPORT_ARCH 32768
|
||||
#define MASK_SUPPORT_ARCH (1 << 30)
|
||||
#define TARGET_SUPPORT_ARCH (target_flags & MASK_SUPPORT_ARCH)
|
||||
|
||||
/* These are for target os support and cannot be changed at runtime. */
|
||||
@ -185,26 +188,32 @@ extern enum alpha_fp_trap_mode alpha_fptm;
|
||||
where VALUE is the bits to set or minus the bits to clear.
|
||||
An empty string NAME is used to identify the default VALUE. */
|
||||
|
||||
#define TARGET_SWITCHES \
|
||||
{ {"no-soft-float", MASK_FP}, \
|
||||
{"soft-float", - MASK_FP}, \
|
||||
{"fp-regs", MASK_FPREGS}, \
|
||||
{"no-fp-regs", - (MASK_FP|MASK_FPREGS)}, \
|
||||
{"alpha-as", -MASK_GAS}, \
|
||||
{"gas", MASK_GAS}, \
|
||||
{"ieee-conformant", MASK_IEEE_CONFORMANT}, \
|
||||
{"ieee", MASK_IEEE|MASK_IEEE_CONFORMANT}, \
|
||||
{"ieee-with-inexact", MASK_IEEE_WITH_INEXACT|MASK_IEEE_CONFORMANT}, \
|
||||
{"build-constants", MASK_BUILD_CONSTANTS}, \
|
||||
{"float-vax", MASK_FLOAT_VAX}, \
|
||||
{"float-ieee", -MASK_FLOAT_VAX}, \
|
||||
{"bwx", MASK_BWX}, \
|
||||
{"no-bwx", -MASK_BWX}, \
|
||||
{"cix", MASK_CIX}, \
|
||||
{"no-cix", -MASK_CIX}, \
|
||||
{"max", MASK_MAX}, \
|
||||
{"no-max", -MASK_MAX}, \
|
||||
{"", TARGET_DEFAULT | TARGET_CPU_DEFAULT} }
|
||||
#define TARGET_SWITCHES \
|
||||
{ {"no-soft-float", MASK_FP, "Use hardware fp"}, \
|
||||
{"soft-float", - MASK_FP, "Do not use hardware fp"}, \
|
||||
{"fp-regs", MASK_FPREGS, "Use fp registers"}, \
|
||||
{"no-fp-regs", - (MASK_FP|MASK_FPREGS), "Do not use fp registers"}, \
|
||||
{"alpha-as", -MASK_GAS, "Do not assume GAS"}, \
|
||||
{"gas", MASK_GAS, "Assume GAS"}, \
|
||||
{"ieee-conformant", MASK_IEEE_CONFORMANT, \
|
||||
"Request IEEE-conformant math library routines (OSF/1)"}, \
|
||||
{"ieee", MASK_IEEE|MASK_IEEE_CONFORMANT, \
|
||||
"Emit IEEE-conformant code, without inexact exceptions"}, \
|
||||
{"ieee-with-inexact", MASK_IEEE_WITH_INEXACT|MASK_IEEE_CONFORMANT, \
|
||||
"Emit IEEE-conformant code, with inexact exceptions"}, \
|
||||
{"build-constants", MASK_BUILD_CONSTANTS, \
|
||||
"Do not emit complex integer constants to read-only memory"}, \
|
||||
{"float-vax", MASK_FLOAT_VAX, "Use VAX fp"}, \
|
||||
{"float-ieee", -MASK_FLOAT_VAX, "Do not use VAX fp"}, \
|
||||
{"bwx", MASK_BWX, "Emit code for the byte/word ISA extension"}, \
|
||||
{"no-bwx", -MASK_BWX, ""}, \
|
||||
{"max", MASK_MAX, "Emit code for the motion video ISA extension"}, \
|
||||
{"no-max", -MASK_MAX, ""}, \
|
||||
{"fix", MASK_FIX, "Emit code for the fp move and sqrt ISA extension"}, \
|
||||
{"no-fix", -MASK_FIX, ""}, \
|
||||
{"cix", MASK_CIX, "Emit code for the counting ISA extension"}, \
|
||||
{"no-cix", -MASK_CIX, ""}, \
|
||||
{"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} }
|
||||
|
||||
#define TARGET_DEFAULT MASK_FP|MASK_FPREGS
|
||||
|
||||
@ -229,19 +238,24 @@ extern enum alpha_fp_trap_mode alpha_fptm;
|
||||
extern char *m88k_short_data;
|
||||
#define TARGET_OPTIONS { { "short-data-", &m88k_short_data } } */
|
||||
|
||||
extern char *alpha_cpu_string; /* For -mcpu= */
|
||||
extern char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */
|
||||
extern char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */
|
||||
extern char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */
|
||||
extern char *alpha_mlat_string; /* For -mmemory-latency= */
|
||||
extern const char *alpha_cpu_string; /* For -mcpu= */
|
||||
extern const char *alpha_fprm_string; /* For -mfp-rounding-mode=[n|m|c|d] */
|
||||
extern const char *alpha_fptm_string; /* For -mfp-trap-mode=[n|u|su|sui] */
|
||||
extern const char *alpha_tp_string; /* For -mtrap-precision=[p|f|i] */
|
||||
extern const char *alpha_mlat_string; /* For -mmemory-latency= */
|
||||
|
||||
#define TARGET_OPTIONS \
|
||||
{ \
|
||||
{"cpu=", &alpha_cpu_string}, \
|
||||
{"fp-rounding-mode=", &alpha_fprm_string}, \
|
||||
{"fp-trap-mode=", &alpha_fptm_string}, \
|
||||
{"trap-precision=", &alpha_tp_string}, \
|
||||
{"memory-latency=", &alpha_mlat_string}, \
|
||||
#define TARGET_OPTIONS \
|
||||
{ \
|
||||
{"cpu=", &alpha_cpu_string, \
|
||||
"Generate code for a given CPU"}, \
|
||||
{"fp-rounding-mode=", &alpha_fprm_string, \
|
||||
"Control the generated fp rounding mode"}, \
|
||||
{"fp-trap-mode=", &alpha_fptm_string, \
|
||||
"Control the IEEE trap mode"}, \
|
||||
{"trap-precision=", &alpha_tp_string, \
|
||||
"Control the precision given to fp exceptions"}, \
|
||||
{"memory-latency=", &alpha_mlat_string, \
|
||||
"Tune expected memory latency"}, \
|
||||
}
|
||||
|
||||
/* Attempt to describe CPU characteristics to the preprocessor. */
|
||||
@ -249,6 +263,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
|
||||
/* Corresponding to amask... */
|
||||
#define CPP_AM_BWX_SPEC "-D__alpha_bwx__ -Acpu(bwx)"
|
||||
#define CPP_AM_MAX_SPEC "-D__alpha_max__ -Acpu(max)"
|
||||
#define CPP_AM_FIX_SPEC "-D__alpha_fix__ -Acpu(fix)"
|
||||
#define CPP_AM_CIX_SPEC "-D__alpha_cix__ -Acpu(cix)"
|
||||
|
||||
/* Corresponding to implver... */
|
||||
@ -261,7 +276,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
|
||||
#define CPP_CPU_EV5_SPEC "%(cpp_im_ev5)"
|
||||
#define CPP_CPU_EV56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx)"
|
||||
#define CPP_CPU_PCA56_SPEC "%(cpp_im_ev5) %(cpp_am_bwx) %(cpp_am_max)"
|
||||
#define CPP_CPU_EV6_SPEC "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_cix)"
|
||||
#define CPP_CPU_EV6_SPEC "%(cpp_im_ev6) %(cpp_am_bwx) %(cpp_am_max) %(cpp_am_fix)"
|
||||
|
||||
#ifndef CPP_CPU_DEFAULT_SPEC
|
||||
# if TARGET_CPU_DEFAULT & MASK_CPU_EV6
|
||||
@ -311,6 +326,7 @@ extern char *alpha_mlat_string; /* For -mmemory-latency= */
|
||||
#define EXTRA_SPECS \
|
||||
{ "cpp_am_bwx", CPP_AM_BWX_SPEC }, \
|
||||
{ "cpp_am_max", CPP_AM_MAX_SPEC }, \
|
||||
{ "cpp_am_fix", CPP_AM_FIX_SPEC }, \
|
||||
{ "cpp_am_cix", CPP_AM_CIX_SPEC }, \
|
||||
{ "cpp_im_ev4", CPP_IM_EV4_SPEC }, \
|
||||
{ "cpp_im_ev5", CPP_IM_EV5_SPEC }, \
|
||||
@ -483,7 +499,7 @@ extern void override_options ();
|
||||
Alpha we'll get better performance by aligning on an octaword
|
||||
boundary. */
|
||||
|
||||
#define ALIGN_LABEL_AFTER_BARRIER(FILE) \
|
||||
#define LABEL_ALIGN_AFTER_BARRIER(FILE) \
|
||||
(optimize > 0 && write_symbols != SDB_DEBUG ? 4 : 0)
|
||||
|
||||
/* No data type wants to be aligned rounder than this. */
|
||||
@ -613,17 +629,20 @@ extern void override_options ();
|
||||
registers can hold 32-bit and 64-bit integers as well, but not 16-bit
|
||||
or 8-bit values. */
|
||||
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
|
||||
((REGNO) < 32 || ((MODE) != QImode && (MODE) != HImode))
|
||||
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
|
||||
((REGNO) >= 32 && (REGNO) <= 62 \
|
||||
? GET_MODE_UNIT_SIZE (MODE) == 8 || GET_MODE_UNIT_SIZE (MODE) == 4 \
|
||||
: 1)
|
||||
|
||||
/* Value is 1 if it is a good idea to tie two pseudo registers
|
||||
when one has mode MODE1 and one has mode MODE2.
|
||||
If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
|
||||
for any hard reg, then this must be 0 for correct output. */
|
||||
/* A C expression that is nonzero if a value of mode
|
||||
MODE1 is accessible in mode MODE2 without copying.
|
||||
|
||||
This asymmetric test is true when MODE1 could be put
|
||||
in an FP register but MODE2 could not. */
|
||||
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
((MODE1) == QImode || (MODE1) == HImode \
|
||||
? (MODE2) == QImode || (MODE2) == HImode \
|
||||
(HARD_REGNO_MODE_OK (32, (MODE1)) \
|
||||
? HARD_REGNO_MODE_OK (32, (MODE2)) \
|
||||
: 1)
|
||||
|
||||
/* Specify the registers used for certain standard purposes.
|
||||
@ -771,11 +790,12 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
|
||||
'S' is a 6-bit constant (valid for a shift insn). */
|
||||
|
||||
#define EXTRA_CONSTRAINT(OP, C) \
|
||||
((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) != AND \
|
||||
((C) == 'Q' ? normal_memory_operand (OP, VOIDmode) \
|
||||
: (C) == 'R' ? current_file_function_operand (OP, Pmode) \
|
||||
: (C) == 'S' ? (GET_CODE (OP) == CONST_INT \
|
||||
&& (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \
|
||||
: 0)
|
||||
extern int normal_memory_operand ();
|
||||
|
||||
/* Given an rtx X being reloaded into a reg required to be
|
||||
in class CLASS, return the class of reg to actually use.
|
||||
@ -807,7 +827,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
|
||||
&& (((CLASS) == FLOAT_REGS \
|
||||
&& ((MODE) == SImode || (MODE) == HImode || (MODE) == QImode)) \
|
||||
|| (((MODE) == QImode || (MODE) == HImode) \
|
||||
&& ! TARGET_BWX && unaligned_memory_operand (IN, MODE)))) \
|
||||
&& ! TARGET_BWX && ! aligned_memory_operand (IN, MODE)))) \
|
||||
? GENERAL_REGS \
|
||||
: ((CLASS) == FLOAT_REGS && GET_CODE (IN) == MEM \
|
||||
&& GET_CODE (XEXP (IN, 0)) == AND) ? GENERAL_REGS \
|
||||
@ -835,10 +855,10 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
|
||||
: NO_REGS)
|
||||
|
||||
/* If we are copying between general and FP registers, we need a memory
|
||||
location unless the CIX extension is available. */
|
||||
location unless the FIX extension is available. */
|
||||
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
|
||||
(! TARGET_CIX && (CLASS1) != (CLASS2))
|
||||
(! TARGET_FIX && (CLASS1) != (CLASS2))
|
||||
|
||||
/* Specify the mode to be used for memory when a secondary memory
|
||||
location is needed. If MODE is floating-point, use it. Otherwise,
|
||||
@ -871,7 +891,7 @@ enum reg_class { NO_REGS, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
|
||||
#define REGISTER_MOVE_COST(CLASS1, CLASS2) \
|
||||
(((CLASS1) == FLOAT_REGS) == ((CLASS2) == FLOAT_REGS) \
|
||||
? 2 \
|
||||
: TARGET_CIX ? 3 : 4+2*alpha_memory_latency)
|
||||
: TARGET_FIX ? 3 : 4+2*alpha_memory_latency)
|
||||
|
||||
/* A C expressions returning the cost of moving data of MODE from a register to
|
||||
or from memory.
|
||||
@ -989,26 +1009,25 @@ extern int alpha_memory_latency;
|
||||
On Alpha the value is found in $0 for integer functions and
|
||||
$f0 for floating-point functions. */
|
||||
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
||||
gen_rtx (REG, \
|
||||
((INTEGRAL_TYPE_P (VALTYPE) \
|
||||
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|
||||
|| POINTER_TYPE_P (VALTYPE)) \
|
||||
? word_mode : TYPE_MODE (VALTYPE), \
|
||||
((TARGET_FPREGS \
|
||||
&& (TREE_CODE (VALTYPE) == REAL_TYPE \
|
||||
|| TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
|
||||
? 32 : 0))
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
||||
gen_rtx_REG (((INTEGRAL_TYPE_P (VALTYPE) \
|
||||
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|
||||
|| POINTER_TYPE_P (VALTYPE)) \
|
||||
? word_mode : TYPE_MODE (VALTYPE), \
|
||||
((TARGET_FPREGS \
|
||||
&& (TREE_CODE (VALTYPE) == REAL_TYPE \
|
||||
|| TREE_CODE (VALTYPE) == COMPLEX_TYPE)) \
|
||||
? 32 : 0))
|
||||
|
||||
/* Define how to find the value returned by a library function
|
||||
assuming the value has mode MODE. */
|
||||
|
||||
#define LIBCALL_VALUE(MODE) \
|
||||
gen_rtx (REG, MODE, \
|
||||
(TARGET_FPREGS \
|
||||
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
|
||||
? 32 : 0))
|
||||
#define LIBCALL_VALUE(MODE) \
|
||||
gen_rtx_REG (MODE, \
|
||||
(TARGET_FPREGS \
|
||||
&& (GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
|
||||
? 32 : 0))
|
||||
|
||||
/* The definition of this macro implies that there are cases where
|
||||
a scalar value cannot be returned in registers.
|
||||
@ -1182,6 +1201,10 @@ extern struct rtx_def *alpha_builtin_saveregs ();
|
||||
extern struct rtx_def *alpha_compare_op0, *alpha_compare_op1;
|
||||
extern int alpha_compare_fp_p;
|
||||
|
||||
/* Define the information needed to modify the epilogue for EH. */
|
||||
|
||||
extern struct rtx_def *alpha_eh_epilogue_sp_ofs;
|
||||
|
||||
/* Make (or fake) .linkage entry for function call.
|
||||
IS_LOCAL is 0 if name is used in call, 1 if name is used in definition. */
|
||||
extern void alpha_need_linkage ();
|
||||
@ -1293,6 +1316,7 @@ do { \
|
||||
|
||||
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
|
||||
alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 16, 24, 8)
|
||||
extern void alpha_initialize_trampoline ();
|
||||
|
||||
/* A C expression whose value is RTL representing the value of the return
|
||||
address for the frame COUNT steps up from the current frame.
|
||||
@ -1302,6 +1326,9 @@ do { \
|
||||
#define RETURN_ADDR_RTX alpha_return_addr
|
||||
extern struct rtx_def *alpha_return_addr ();
|
||||
|
||||
/* Before the prologue, RA lives in $26. */
|
||||
#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, 26)
|
||||
|
||||
/* Initialize data used by insn expanders. This is called from insn_emit,
|
||||
once for every function before code is generated. */
|
||||
|
||||
@ -1310,11 +1337,11 @@ extern void alpha_init_expanders ();
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
|
||||
/* #define HAVE_POST_INCREMENT */
|
||||
/* #define HAVE_POST_DECREMENT */
|
||||
/* #define HAVE_POST_INCREMENT 0 */
|
||||
/* #define HAVE_POST_DECREMENT 0 */
|
||||
|
||||
/* #define HAVE_PRE_DECREMENT */
|
||||
/* #define HAVE_PRE_INCREMENT */
|
||||
/* #define HAVE_PRE_DECREMENT 0 */
|
||||
/* #define HAVE_PRE_INCREMENT 0 */
|
||||
|
||||
/* Macros to check register numbers against specific register classes. */
|
||||
|
||||
@ -1365,18 +1392,32 @@ extern void alpha_init_expanders ();
|
||||
/* Nonzero if X is a hard reg that can be used as an index
|
||||
or if it is a pseudo reg. */
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg
|
||||
or if it is a pseudo reg. */
|
||||
#define REG_OK_FOR_BASE_P(X) \
|
||||
(REGNO (X) < 32 || REGNO (X) == 63 || REGNO (X) >= FIRST_PSEUDO_REGISTER)
|
||||
|
||||
/* ??? Nonzero if X is the frame pointer, or some virtual register
|
||||
that may eliminate to the frame pointer. These will be allowed to
|
||||
have offsets greater than 32K. This is done because register
|
||||
elimination offsets will change the hi/lo split, and if we split
|
||||
before reload, we will require additional instructions. */
|
||||
#define REG_OK_FP_BASE_P(X) \
|
||||
(REGNO (X) == 31 || REGNO (X) == 63 \
|
||||
|| (REGNO (X) >= FIRST_PSEUDO_REGISTER \
|
||||
&& REGNO (X) < LAST_VIRTUAL_REGISTER))
|
||||
|
||||
#else
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as an index. */
|
||||
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
|
||||
|
||||
/* Nonzero if X is a hard reg that can be used as a base reg. */
|
||||
#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||
|
||||
#define REG_OK_FP_BASE_P(X) 0
|
||||
|
||||
#endif
|
||||
|
||||
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
|
||||
@ -1391,16 +1432,34 @@ extern void alpha_init_expanders ();
|
||||
|
||||
First define the basic valid address. */
|
||||
|
||||
#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \
|
||||
{ if (REG_P (X) && REG_OK_FOR_BASE_P (X)) \
|
||||
goto ADDR; \
|
||||
if (CONSTANT_ADDRESS_P (X)) \
|
||||
goto ADDR; \
|
||||
if (GET_CODE (X) == PLUS \
|
||||
&& REG_P (XEXP (X, 0)) \
|
||||
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
|
||||
&& CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
||||
goto ADDR; \
|
||||
#define GO_IF_LEGITIMATE_SIMPLE_ADDRESS(MODE, X, ADDR) \
|
||||
{ \
|
||||
rtx tmp = (X); \
|
||||
if (GET_CODE (tmp) == SUBREG \
|
||||
&& (GET_MODE_SIZE (GET_MODE (tmp)) \
|
||||
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \
|
||||
tmp = SUBREG_REG (tmp); \
|
||||
if (REG_P (tmp) && REG_OK_FOR_BASE_P (tmp)) \
|
||||
goto ADDR; \
|
||||
if (CONSTANT_ADDRESS_P (X)) \
|
||||
goto ADDR; \
|
||||
if (GET_CODE (X) == PLUS) \
|
||||
{ \
|
||||
tmp = XEXP (X, 0); \
|
||||
if (GET_CODE (tmp) == SUBREG \
|
||||
&& (GET_MODE_SIZE (GET_MODE (tmp)) \
|
||||
< GET_MODE_SIZE (GET_MODE (SUBREG_REG (tmp))))) \
|
||||
tmp = SUBREG_REG (tmp); \
|
||||
if (REG_P (tmp)) \
|
||||
{ \
|
||||
if (REG_OK_FP_BASE_P (tmp) \
|
||||
&& GET_CODE (XEXP (X, 1)) == CONST_INT) \
|
||||
goto ADDR; \
|
||||
if (REG_OK_FOR_BASE_P (tmp) \
|
||||
&& CONSTANT_ADDRESS_P (XEXP (X, 1))) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Now accept the simple address, or, for DImode only, an AND of a simple
|
||||
@ -1596,9 +1655,11 @@ do { \
|
||||
|
||||
#define MOVE_MAX 8
|
||||
|
||||
/* Controls how many units are moved by expr.c before resorting to movstr.
|
||||
Without byte/word accesses, we want no more than one; with, several single
|
||||
byte accesses are better. */
|
||||
/* If a memory-to-memory move would take MOVE_RATIO or more simple
|
||||
move-instruction pairs, we will do a movstr or libcall instead.
|
||||
|
||||
Without byte/word accesses, we want no more than four instructions;
|
||||
with, several single byte accesses are better. */
|
||||
|
||||
#define MOVE_RATIO (TARGET_BWX ? 7 : 2)
|
||||
|
||||
@ -1693,6 +1754,12 @@ do { \
|
||||
/* The EV4 is dual issue; EV5/EV6 are quad issue. */
|
||||
#define ISSUE_RATE (alpha_cpu == PROCESSOR_EV4 ? 2 : 4)
|
||||
|
||||
/* Describe the fact that MULTI instructions are multiple instructions
|
||||
and so to assume they don't pair with anything. */
|
||||
#define MD_SCHED_VARIABLE_ISSUE(DUMP, SCHED_VERBOSE, INSN, CAN_ISSUE_MORE) \
|
||||
if (recog_memoized (INSN) < 0 || get_attr_type (INSN) == TYPE_MULTI) \
|
||||
(CAN_ISSUE_MORE) = 0
|
||||
|
||||
/* Compute the cost of computing a constant rtl expression RTX
|
||||
whose rtx-code is CODE. The body of this macro is a portion
|
||||
of a switch statement. If the code is computed here,
|
||||
@ -1970,7 +2037,7 @@ literal_section () \
|
||||
This is suitable for output with `assemble_name'. */
|
||||
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
|
||||
sprintf (LABEL, "*$%s%d", PREFIX, NUM)
|
||||
sprintf ((LABEL), "*$%s%ld", (PREFIX), (long)(NUM))
|
||||
|
||||
/* Check a floating-point value for validity for a particular machine mode. */
|
||||
|
||||
@ -2078,6 +2145,11 @@ literal_section () \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* To get unaligned data, we have to turn off auto alignment. */
|
||||
#define UNALIGNED_SHORT_ASM_OP ".align 0\n\t.word"
|
||||
#define UNALIGNED_INT_ASM_OP ".align 0\n\t.long"
|
||||
#define UNALIGNED_DOUBLE_INT_ASM_OP ".align 0\n\t.quad"
|
||||
|
||||
/* This is how to output an insn to push a register on the stack.
|
||||
It need not be very fast code. */
|
||||
|
||||
@ -2237,41 +2309,22 @@ do { \
|
||||
|
||||
/* Print a memory address as an operand to reference that memory location. */
|
||||
|
||||
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
|
||||
{ rtx addr = (ADDR); \
|
||||
int basereg = 31; \
|
||||
HOST_WIDE_INT offset = 0; \
|
||||
\
|
||||
if (GET_CODE (addr) == AND) \
|
||||
addr = XEXP (addr, 0); \
|
||||
\
|
||||
if (GET_CODE (addr) == REG) \
|
||||
basereg = REGNO (addr); \
|
||||
else if (GET_CODE (addr) == CONST_INT) \
|
||||
offset = INTVAL (addr); \
|
||||
else if (GET_CODE (addr) == PLUS \
|
||||
&& GET_CODE (XEXP (addr, 0)) == REG \
|
||||
&& GET_CODE (XEXP (addr, 1)) == CONST_INT) \
|
||||
basereg = REGNO (XEXP (addr, 0)), offset = INTVAL (XEXP (addr, 1)); \
|
||||
else \
|
||||
abort (); \
|
||||
\
|
||||
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, offset); \
|
||||
fprintf (FILE, "($%d)", basereg); \
|
||||
}
|
||||
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
|
||||
print_operand_address((FILE), (ADDR))
|
||||
|
||||
/* Define the codes that are matched by predicates in alpha.c. */
|
||||
|
||||
#define PREDICATE_CODES \
|
||||
{"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"cint8_operand", {CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"sext_add_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"cint8_operand", {CONST_INT}}, \
|
||||
{"reg_or_cint_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"add_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"sext_add_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"const48_operand", {CONST_INT}}, \
|
||||
{"and_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"or_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
|
||||
{"and_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"or_operand", {SUBREG, REG, CONST_INT}}, \
|
||||
{"mode_mask_operand", {CONST_INT}}, \
|
||||
{"mul8_operand", {CONST_INT}}, \
|
||||
{"mode_width_operand", {CONST_INT}}, \
|
||||
@ -2284,14 +2337,16 @@ do { \
|
||||
{"current_file_function_operand", {SYMBOL_REF}}, \
|
||||
{"call_operand", {REG, SYMBOL_REF}}, \
|
||||
{"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
|
||||
SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}}, \
|
||||
SYMBOL_REF, CONST, LABEL_REF}}, \
|
||||
{"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
|
||||
SYMBOL_REF, CONST, LABEL_REF, CONSTANT_P_RTX}}, \
|
||||
SYMBOL_REF, CONST, LABEL_REF}}, \
|
||||
{"aligned_memory_operand", {MEM}}, \
|
||||
{"unaligned_memory_operand", {MEM}}, \
|
||||
{"reg_or_unaligned_mem_operand", {SUBREG, REG, MEM}}, \
|
||||
{"any_memory_operand", {MEM}}, \
|
||||
{"hard_fp_register_operand", {SUBREG, REG}},
|
||||
{"hard_fp_register_operand", {SUBREG, REG}}, \
|
||||
{"reg_not_elim_operand", {SUBREG, REG}}, \
|
||||
{"reg_no_subreg_operand", {REG}},
|
||||
|
||||
/* Tell collect that the object format is ECOFF. */
|
||||
#define OBJECT_FORMAT_COFF
|
||||
@ -2462,6 +2517,7 @@ extern int current_file_function_operand ();
|
||||
extern int alpha_sa_size ();
|
||||
extern int alpha_adjust_cost ();
|
||||
extern void print_operand ();
|
||||
extern void print_operand_address ();
|
||||
extern int reg_or_0_operand ();
|
||||
extern int reg_or_8bit_operand ();
|
||||
extern int mul8_operand ();
|
||||
@ -2482,6 +2538,7 @@ extern int divmod_operator ();
|
||||
extern int call_operand ();
|
||||
extern int reg_or_cint_operand ();
|
||||
extern int hard_fp_register_operand ();
|
||||
extern int reg_not_elim_operand ();
|
||||
extern void alpha_set_memflags ();
|
||||
extern int aligned_memory_operand ();
|
||||
extern void get_aligned_mem ();
|
||||
|
File diff suppressed because it is too large
Load Diff
104
contrib/gcc/config/alpha/alpha32.h
Normal file
104
contrib/gcc/config/alpha/alpha32.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha
|
||||
running Windows/NT.
|
||||
Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
Derived from code
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
Donn Terry, Softway Systems, Inc.
|
||||
|
||||
This file contains the code-generation stuff common to the 32-bit
|
||||
versions of the DEC/Compaq Alpha architecture. It is shared by
|
||||
Interix and NT/Win32 ports. It should not contain compile-time
|
||||
or run-time dependent environment values (such as compiler options
|
||||
or anything containing a file or pathname.)
|
||||
|
||||
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. */
|
||||
|
||||
#undef TARGET_WINDOWS_NT
|
||||
#define TARGET_WINDOWS_NT 1
|
||||
|
||||
/* WinNT (and thus Interix) use unsigned int */
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
/* Pointer is 32 bits but the hardware has 64-bit addresses, sign extended. */
|
||||
#undef POINTER_SIZE
|
||||
#define POINTER_SIZE 32
|
||||
#define POINTERS_EXTEND_UNSIGNED 0
|
||||
|
||||
/* We don't change Pmode to the "obvious" SI mode... the above appears
|
||||
to affect the in-memory size; we want the registers to stay DImode
|
||||
to match the md file */
|
||||
|
||||
/* "long" is 32 bits. */
|
||||
#undef LONG_TYPE_SIZE
|
||||
#define LONG_TYPE_SIZE 32
|
||||
|
||||
|
||||
/* Output assembler code for a block containing the constant parts
|
||||
of a trampoline, leaving space for the variable parts.
|
||||
|
||||
The trampoline should set the static chain pointer to value placed
|
||||
into the trampoline and should branch to the specified routine. */
|
||||
|
||||
#undef TRAMPOLINE_TEMPLATE
|
||||
#define TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
fprintf (FILE, "\tbr $27,$LTRAMPP\n"); \
|
||||
fprintf (FILE, "$LTRAMPP:\n\tldl $1,12($27)\n"); \
|
||||
fprintf (FILE, "\tldl $27,16($27)\n"); \
|
||||
fprintf (FILE, "\tjmp $31,($27),0\n"); \
|
||||
fprintf (FILE, "\t.long 0,0\n"); \
|
||||
}
|
||||
|
||||
/* Length in units of the trampoline for entering a nested function. */
|
||||
|
||||
#undef TRAMPOLINE_SIZE
|
||||
#define TRAMPOLINE_SIZE 24
|
||||
|
||||
/* Emit RTL insns to initialize the variable parts of a trampoline.
|
||||
FNADDR is an RTX for the address of the function's pure code.
|
||||
CXT is an RTX for the static chain value for the function. */
|
||||
|
||||
#undef INITIALIZE_TRAMPOLINE
|
||||
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
|
||||
alpha_initialize_trampoline (TRAMP, FNADDR, CXT, 20, 16, 12)
|
||||
|
||||
/* Output code to add DELTA to the first argument, and then jump to FUNCTION.
|
||||
Used for C++ multiple inheritance. */
|
||||
|
||||
#undef ASM_OUTPUT_MI_THUNK
|
||||
#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \
|
||||
do { \
|
||||
char *op, *fn_name = XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0); \
|
||||
int reg; \
|
||||
\
|
||||
/* Mark end of prologue. */ \
|
||||
output_end_prologue (FILE); \
|
||||
\
|
||||
/* Rely on the assembler to macro expand a large delta. */ \
|
||||
reg = aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? 17 : 16; \
|
||||
fprintf (FILE, "\tlda $%d,%ld($%d)\n", reg, (long)(DELTA), reg); \
|
||||
\
|
||||
op = "jsr"; \
|
||||
if (current_file_function_operand (XEXP (DECL_RTL (FUNCTION), 0))) \
|
||||
op = "br"; \
|
||||
fprintf (FILE, "\t%s $31,", op); \
|
||||
assemble_name (FILE, fn_name); \
|
||||
fputc ('\n', FILE); \
|
||||
} while (0)
|
@ -50,6 +50,8 @@ __CTOR_LIST__:
|
||||
__DTOR_LIST__:
|
||||
.quad -1
|
||||
|
||||
.section .eh_frame,"aw"
|
||||
__EH_FRAME_BEGIN__:
|
||||
|
||||
#
|
||||
# Fragment of the ELF _fini routine that invokes our dtor cleanup.
|
||||
@ -67,10 +69,25 @@ __DTOR_LIST__:
|
||||
1: ldgp $29,0($29)
|
||||
jsr $26,__do_global_dtors_aux
|
||||
|
||||
# Ideally this call would go in crtend.o, except that we can't
|
||||
# get hold of __EH_FRAME_BEGIN__ there.
|
||||
|
||||
jsr $26,__do_frame_takedown
|
||||
|
||||
# Must match the alignment we got from crti.o else we get
|
||||
# zero-filled holes in our _fini function and then SIGILL.
|
||||
.align 3
|
||||
|
||||
#
|
||||
# Fragment of the ELF _init routine that sets up the frame info.
|
||||
#
|
||||
|
||||
.section .init,"ax"
|
||||
br $29,1f
|
||||
1: ldgp $29,0($29)
|
||||
jsr $26,__do_frame_setup
|
||||
.align 3
|
||||
|
||||
#
|
||||
# Invoke our destructors in order.
|
||||
#
|
||||
@ -78,7 +95,7 @@ __DTOR_LIST__:
|
||||
.data
|
||||
|
||||
# Support recursive calls to exit.
|
||||
9: .quad __DTOR_LIST__
|
||||
$ptr: .quad __DTOR_LIST__
|
||||
|
||||
.text
|
||||
|
||||
@ -86,15 +103,14 @@ __DTOR_LIST__:
|
||||
.ent __do_global_dtors_aux
|
||||
|
||||
__do_global_dtors_aux:
|
||||
ldgp $29,0($27)
|
||||
lda $30,-16($30)
|
||||
.frame $30,16,$26,0
|
||||
stq $9,8($30)
|
||||
stq $26,0($30)
|
||||
.mask 0x4000200,-16
|
||||
.prologue 1
|
||||
.prologue 0
|
||||
|
||||
lda $9,9b
|
||||
lda $9,$ptr
|
||||
br 1f
|
||||
0: stq $1,0($9)
|
||||
jsr $26,($27)
|
||||
@ -109,3 +125,68 @@ __do_global_dtors_aux:
|
||||
ret
|
||||
|
||||
.end __do_global_dtors_aux
|
||||
|
||||
#
|
||||
# Install our frame info.
|
||||
#
|
||||
|
||||
# ??? How can we rationally keep this size correct?
|
||||
|
||||
.section .bss
|
||||
.type $object,@object
|
||||
.align 3
|
||||
$object:
|
||||
.zero 48
|
||||
.size $object, 48
|
||||
|
||||
.text
|
||||
|
||||
.align 3
|
||||
.ent __do_frame_setup
|
||||
|
||||
__do_frame_setup:
|
||||
ldgp $29,0($27)
|
||||
lda $30,-16($30)
|
||||
.frame $30,16,$26,0
|
||||
stq $26,0($30)
|
||||
.mask 0x4000000,-16
|
||||
.prologue 1
|
||||
|
||||
lda $1,__register_frame_info
|
||||
beq $1,0f
|
||||
lda $16,__EH_FRAME_BEGIN__
|
||||
lda $17,$object
|
||||
jsr $26,__register_frame_info
|
||||
ldq $26,0($30)
|
||||
0: lda $30,16($30)
|
||||
ret
|
||||
|
||||
.end __do_frame_setup
|
||||
|
||||
#
|
||||
# Remove our frame info.
|
||||
#
|
||||
|
||||
.align 3
|
||||
.ent __do_frame_takedown
|
||||
|
||||
__do_frame_takedown:
|
||||
ldgp $29,0($27)
|
||||
lda $30,-16($30)
|
||||
.frame $30,16,$26,0
|
||||
stq $26,0($30)
|
||||
.mask 0x4000000,-16
|
||||
.prologue 1
|
||||
|
||||
lda $1,__deregister_frame_info
|
||||
beq $1,0f
|
||||
lda $16,__EH_FRAME_BEGIN__
|
||||
jsr $26,__deregister_frame_info
|
||||
ldq $26,0($30)
|
||||
0: lda $30,16($30)
|
||||
ret
|
||||
|
||||
.end __do_frame_takedown
|
||||
|
||||
.weak __register_frame_info
|
||||
.weak __deregister_frame_info
|
||||
|
@ -50,6 +50,9 @@ __CTOR_END__:
|
||||
__DTOR_END__:
|
||||
.quad 0
|
||||
|
||||
.section .eh_frame,"aw"
|
||||
__FRAME_END__:
|
||||
.quad 0
|
||||
|
||||
#
|
||||
# Fragment of the ELF _init routine that invokes our ctor startup
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha w/ELF.
|
||||
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
Contributed by Richard Henderson (rth@tamu.edu).
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#define OBJECT_FORMAT_ELF
|
||||
|
||||
#define DBX_DEBUGGING_INFO
|
||||
#define DWARF2_DEBUGGING_INFO
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
@ -34,7 +35,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#define CC1_SPEC "%{G*}"
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC "%{G*} %{relax:-relax}"
|
||||
#define ASM_SPEC "%{G*} %{relax:-relax} %{gdwarf*:-no-mdebug}"
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-m elf64alpha %{G*} %{relax:-relax} \
|
||||
@ -49,18 +50,21 @@ Boston, MA 02111-1307, USA. */
|
||||
/* Output at beginning of assembler file. */
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
{ \
|
||||
alpha_write_verstamp (FILE); \
|
||||
output_file_directive (FILE, main_input_filename); \
|
||||
do { \
|
||||
if (write_symbols != DWARF2_DEBUG) \
|
||||
{ \
|
||||
alpha_write_verstamp (FILE); \
|
||||
output_file_directive (FILE, main_input_filename); \
|
||||
} \
|
||||
fprintf (FILE, "\t.set noat\n"); \
|
||||
fprintf (FILE, "\t.set noreorder\n"); \
|
||||
if (TARGET_BWX | TARGET_MAX | TARGET_CIX) \
|
||||
fprintf (FILE, "\t.set noreorder\n"); \
|
||||
if (TARGET_BWX | TARGET_MAX | TARGET_FIX | TARGET_CIX) \
|
||||
{ \
|
||||
fprintf (FILE, "\t.arch %s\n", \
|
||||
(alpha_cpu == PROCESSOR_EV6 ? "ev6" \
|
||||
: TARGET_MAX ? "pca56" : "ev56")); \
|
||||
} \
|
||||
}
|
||||
} while (0)
|
||||
|
||||
extern void output_file_directive ();
|
||||
|
||||
@ -79,8 +83,9 @@ extern void output_file_directive ();
|
||||
#else
|
||||
#define ASM_FILE_END(FILE) \
|
||||
do { \
|
||||
fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
|
||||
IDENT_ASM_OP, version_string); \
|
||||
if (!flag_no_ident) \
|
||||
fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
|
||||
IDENT_ASM_OP, version_string); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
@ -434,20 +439,23 @@ void FN () \
|
||||
size_directive_output was set
|
||||
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
|
||||
|
||||
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
|
||||
do { \
|
||||
char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
|
||||
&& ! AT_END && TOP_LEVEL \
|
||||
&& DECL_INITIAL (DECL) == error_mark_node \
|
||||
&& !size_directive_output) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, name); \
|
||||
fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
} \
|
||||
} while (0)
|
||||
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
|
||||
do { \
|
||||
char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
|
||||
&& ! AT_END && TOP_LEVEL \
|
||||
&& DECL_INITIAL (DECL) == error_mark_node \
|
||||
&& !size_directive_output) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, name); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, HOST_WIDE_INT_PRINT_DEC, \
|
||||
int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
|
||||
ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
|
||||
@ -518,3 +526,9 @@ do { \
|
||||
|
||||
/* We support #pragma. */
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
|
||||
/* Undo the auto-alignment stuff from alpha.h. ELF has unaligned data
|
||||
pseudos natively. */
|
||||
#undef UNALIGNED_SHORT_ASM_OP
|
||||
#undef UNALIGNED_INT_ASM_OP
|
||||
#undef UNALIGNED_DOUBLE_INT_ASM_OP
|
||||
|
325
contrib/gcc/config/alpha/lib1funcs.asm
Normal file
325
contrib/gcc/config/alpha/lib1funcs.asm
Normal file
@ -0,0 +1,325 @@
|
||||
/* DEC Alpha division and remainder support.
|
||||
Copyright (C) 1994, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file 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.
|
||||
|
||||
In addition to the permissions in the GNU General Public License, the
|
||||
Free Software Foundation gives you unlimited permission to link the
|
||||
compiled version of this file with other programs, and to distribute
|
||||
those programs without any restriction coming from the use of this
|
||||
file. (The General Public License restrictions do apply in other
|
||||
respects; for example, they cover modification of the file, and
|
||||
distribution when not linked into another program.)
|
||||
|
||||
This file 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 this program; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* As a special exception, if you link this library with other files,
|
||||
some of which are compiled with GCC, to produce an executable,
|
||||
this library 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. */
|
||||
|
||||
/* This had to be written in assembler because the division functions
|
||||
use a non-standard calling convention.
|
||||
|
||||
This file provides an implementation of __divqu, __divq, __divlu,
|
||||
__divl, __remqu, __remq, __remlu and __reml. CPP macros control
|
||||
the exact operation.
|
||||
|
||||
Operation performed: $27 := $24 o $25, clobber $28, return address to
|
||||
caller in $23, where o one of the operations.
|
||||
|
||||
The following macros need to be defined:
|
||||
|
||||
SIZE, the number of bits, 32 or 64.
|
||||
|
||||
TYPE, either UNSIGNED or SIGNED
|
||||
|
||||
OPERATION, either DIVISION or REMAINDER
|
||||
|
||||
SPECIAL_CALLING_CONVENTION, 0 or 1. It is useful for debugging to
|
||||
define this to 0. That removes the `__' prefix to make the function
|
||||
name not collide with the existing libc.a names, and uses the
|
||||
standard Alpha procedure calling convention.
|
||||
*/
|
||||
|
||||
#ifndef SPECIAL_CALLING_CONVENTION
|
||||
#define SPECIAL_CALLING_CONVENTION 1
|
||||
#endif
|
||||
|
||||
#ifdef L_divl
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __divl
|
||||
#else
|
||||
#define FUNCTION_NAME divl
|
||||
#endif
|
||||
#define SIZE 32
|
||||
#define TYPE SIGNED
|
||||
#define OPERATION DIVISION
|
||||
#endif
|
||||
|
||||
#ifdef L_divlu
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __divlu
|
||||
#else
|
||||
#define FUNCTION_NAME divlu
|
||||
#endif
|
||||
#define SIZE 32
|
||||
#define TYPE UNSIGNED
|
||||
#define OPERATION DIVISION
|
||||
#endif
|
||||
|
||||
#ifdef L_divq
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __divq
|
||||
#else
|
||||
#define FUNCTION_NAME divq
|
||||
#endif
|
||||
#define SIZE 64
|
||||
#define TYPE SIGNED
|
||||
#define OPERATION DIVISION
|
||||
#endif
|
||||
|
||||
#ifdef L_divqu
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __divqu
|
||||
#else
|
||||
#define FUNCTION_NAME divqu
|
||||
#endif
|
||||
#define SIZE 64
|
||||
#define TYPE UNSIGNED
|
||||
#define OPERATION DIVISION
|
||||
#endif
|
||||
|
||||
#ifdef L_reml
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __reml
|
||||
#else
|
||||
#define FUNCTION_NAME reml
|
||||
#endif
|
||||
#define SIZE 32
|
||||
#define TYPE SIGNED
|
||||
#define OPERATION REMAINDER
|
||||
#endif
|
||||
|
||||
#ifdef L_remlu
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __remlu
|
||||
#else
|
||||
#define FUNCTION_NAME remlu
|
||||
#endif
|
||||
#define SIZE 32
|
||||
#define TYPE UNSIGNED
|
||||
#define OPERATION REMAINDER
|
||||
#endif
|
||||
|
||||
#ifdef L_remq
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __remq
|
||||
#else
|
||||
#define FUNCTION_NAME remq
|
||||
#endif
|
||||
#define SIZE 64
|
||||
#define TYPE SIGNED
|
||||
#define OPERATION REMAINDER
|
||||
#endif
|
||||
|
||||
#ifdef L_remqu
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define FUNCTION_NAME __remqu
|
||||
#else
|
||||
#define FUNCTION_NAME remqu
|
||||
#endif
|
||||
#define SIZE 64
|
||||
#define TYPE UNSIGNED
|
||||
#define OPERATION REMAINDER
|
||||
#endif
|
||||
|
||||
#define tmp0 $3
|
||||
#define tmp1 $28
|
||||
#define cnt $1
|
||||
#define result_sign $2
|
||||
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#define N $24
|
||||
#define D $25
|
||||
#define Q RETREG
|
||||
#define RETREG $27
|
||||
#else
|
||||
#define N $16
|
||||
#define D $17
|
||||
#define Q RETREG
|
||||
#define RETREG $0
|
||||
#endif
|
||||
|
||||
/* Misc symbols to make alpha assembler easier to read. */
|
||||
#define zero $31
|
||||
#define sp $30
|
||||
|
||||
/* Symbols to make interface nicer. */
|
||||
#define UNSIGNED 0
|
||||
#define SIGNED 1
|
||||
#define DIVISION 0
|
||||
#define REMAINDER 1
|
||||
|
||||
.set noreorder
|
||||
.set noat
|
||||
.text
|
||||
.align 3
|
||||
.globl FUNCTION_NAME
|
||||
.ent FUNCTION_NAME
|
||||
FUNCTION_NAME:
|
||||
|
||||
.frame $30,0,$26,0
|
||||
.prologue 0
|
||||
|
||||
/* Under the special calling convention, we have to preserve all register
|
||||
values but $23 and $28. */
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
lda sp,-64(sp)
|
||||
#if OPERATION == DIVISION
|
||||
stq N,0(sp)
|
||||
#endif
|
||||
stq D,8(sp)
|
||||
stq cnt,16(sp)
|
||||
stq result_sign,24(sp)
|
||||
stq tmp0,32(sp)
|
||||
#endif
|
||||
|
||||
/* If we are computing the remainder, move N to the register that is used
|
||||
for the return value, and redefine what register is used for N. */
|
||||
#if OPERATION == REMAINDER
|
||||
bis N,N,RETREG
|
||||
#undef N
|
||||
#define N RETREG
|
||||
#endif
|
||||
|
||||
/* Perform conversion from 32 bit types to 64 bit types. */
|
||||
#if SIZE == 32
|
||||
#if TYPE == SIGNED
|
||||
/* If there are problems with the signed case, add these instructions.
|
||||
The caller should already have done this.
|
||||
addl N,0,N # sign extend N
|
||||
addl D,0,D # sign extend D
|
||||
*/
|
||||
#else /* UNSIGNED */
|
||||
zap N,0xf0,N # zero extend N (caller required to sign extend)
|
||||
zap D,0xf0,D # zero extend D
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Check for divide by zero. */
|
||||
bne D,$34
|
||||
lda $16,-2(zero)
|
||||
call_pal 0xaa
|
||||
$34:
|
||||
|
||||
#if TYPE == SIGNED
|
||||
#if OPERATION == DIVISION
|
||||
xor N,D,result_sign
|
||||
#else
|
||||
bis N,N,result_sign
|
||||
#endif
|
||||
/* Get the absolute values of N and D. */
|
||||
subq zero,N,tmp0
|
||||
cmovlt N,tmp0,N
|
||||
subq zero,D,tmp0
|
||||
cmovlt D,tmp0,D
|
||||
#endif
|
||||
|
||||
/* Compute CNT = ceil(log2(N)) - ceil(log2(D)). This is the number of
|
||||
divide iterations we will have to perform. Should you wish to optimize
|
||||
this, check a few bits at a time, preferably using zap/zapnot. Be
|
||||
careful though, this code runs fast fro the most common cases, when the
|
||||
quotient is small. */
|
||||
bge N,$35
|
||||
bis zero,1,cnt
|
||||
blt D,$40
|
||||
.align 3
|
||||
$39: addq D,D,D
|
||||
addl cnt,1,cnt
|
||||
bge D,$39
|
||||
br zero,$40
|
||||
$35: cmpult N,D,tmp0
|
||||
bis zero,zero,cnt
|
||||
bne tmp0,$42
|
||||
.align 3
|
||||
$44: addq D,D,D
|
||||
cmpult N,D,tmp0
|
||||
addl cnt,1,cnt
|
||||
beq tmp0,$44
|
||||
$42: srl D,1,D
|
||||
$40:
|
||||
subl cnt,1,cnt
|
||||
|
||||
|
||||
/* Actual divide. Could be optimized with unrolling. */
|
||||
#if OPERATION == DIVISION
|
||||
bis zero,zero,Q
|
||||
#endif
|
||||
blt cnt,$46
|
||||
.align 3
|
||||
$49: cmpule D,N,tmp1
|
||||
subq N,D,tmp0
|
||||
srl D,1,D
|
||||
subl cnt,1,cnt
|
||||
cmovne tmp1,tmp0,N
|
||||
#if OPERATION == DIVISION
|
||||
addq Q,Q,Q
|
||||
bis Q,tmp1,Q
|
||||
#endif
|
||||
bge cnt,$49
|
||||
$46:
|
||||
|
||||
|
||||
/* The result is now in RETREG. NOTE! It was written to RETREG using
|
||||
either N or Q as a synonym! */
|
||||
|
||||
|
||||
/* Change the sign of the result as needed. */
|
||||
#if TYPE == SIGNED
|
||||
subq zero,RETREG,tmp0
|
||||
cmovlt result_sign,tmp0,RETREG
|
||||
#endif
|
||||
|
||||
|
||||
/* Restore clobbered registers. */
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
#if OPERATION == DIVISION
|
||||
ldq N,0(sp)
|
||||
#endif
|
||||
ldq D,8(sp)
|
||||
ldq cnt,16(sp)
|
||||
ldq result_sign,24(sp)
|
||||
ldq tmp0,32(sp)
|
||||
|
||||
lda sp,64(sp)
|
||||
#endif
|
||||
|
||||
|
||||
/* Sign extend an *unsigned* 32 bit result, as required by the Alpha
|
||||
conventions. */
|
||||
#if TYPE == UNSIGNED && SIZE == 32
|
||||
/* This could be avoided by adding some CPP hair to the divide loop.
|
||||
It is probably not worth the added complexity. */
|
||||
addl RETREG,0,RETREG
|
||||
#endif
|
||||
|
||||
|
||||
#if SPECIAL_CALLING_CONVENTION
|
||||
ret zero,($23),1
|
||||
#else
|
||||
ret zero,($26),1
|
||||
#endif
|
||||
.end FUNCTION_NAME
|
@ -17,13 +17,14 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ECOFF)");
|
||||
|
||||
#undef SUB_CPP_PREDEFINES
|
||||
#define SUB_CPP_PREDEFINES "-D__ECOFF__"
|
||||
#undef CPP_SUBTARGET_SPEC
|
||||
#define CPP_SUBTARGET_SPEC "-D__ECOFF__"
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-G 8 %{O*:-O3} %{!O*:-O1}"
|
||||
|
@ -17,7 +17,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (Alpha GNU/Linux for ELF)");
|
||||
|
@ -17,14 +17,16 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES \
|
||||
"-Dlinux -Dunix -Asystem(linux) -D_LONGLONG -D__alpha__ " SUB_CPP_PREDEFINES
|
||||
"-Dlinux -Dunix -Asystem(linux) -D_LONGLONG -D__alpha__ " \
|
||||
SUB_CPP_PREDEFINES
|
||||
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "%{pg:-lgmon} %{pg:-lc_p} %{!pg:-lc}"
|
||||
|
@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (Alpha NetBSD/ELF)");
|
||||
|
@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (MASK_FP | MASK_FPREGS | MASK_GAS)
|
||||
|
@ -30,9 +30,19 @@ Boston, MA 02111-1307, USA. */
|
||||
-Dunix -D__osf__ -D_LONGLONG -DSYSTYPE_BSD \
|
||||
-D_SYSTYPE_BSD -Asystem(unix) -Asystem(xpg4)"
|
||||
|
||||
/* Accept DEC C flags for multithreaded programs. We use _PTHREAD_USE_D4
|
||||
instead of PTHREAD_USE_D4 since both have the same effect and the former
|
||||
doesn't invade the users' namespace. */
|
||||
|
||||
#undef CPP_SUBTARGET_SPEC
|
||||
#define CPP_SUBTARGET_SPEC \
|
||||
"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4}"
|
||||
|
||||
/* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf. */
|
||||
|
||||
#define LIB_SPEC "%{p:-lprof1 -lpdf} %{pg:-lprof1 -lpdf} %{a:-lprof2} -lc"
|
||||
#define LIB_SPEC \
|
||||
"%{p|pg:-lprof1%{pthread|threads:_r} -lpdf} %{a:-lprof2} \
|
||||
%{threads: -lpthreads} %{pthread|threads: -lpthread -lmach -lexc} -lc"
|
||||
|
||||
/* Pass "-G 8" to ld because Alpha's CC does. Pass -O3 if we are
|
||||
optimizing, -O1 if we are not. Pass -shared, -non_shared or
|
||||
|
6
contrib/gcc/config/alpha/t-ieee
Normal file
6
contrib/gcc/config/alpha/t-ieee
Normal file
@ -0,0 +1,6 @@
|
||||
# All alphas get an IEEE complaint set of libraries.
|
||||
MULTILIB_OPTIONS = mieee
|
||||
MULTILIB_DIRNAMES = ieee
|
||||
|
||||
LIBGCC = stmp-multilib
|
||||
INSTALL_LIBGCC = install-multilib
|
16
contrib/gcc/config/alpha/t-interix
Normal file
16
contrib/gcc/config/alpha/t-interix
Normal file
@ -0,0 +1,16 @@
|
||||
# t-interix
|
||||
|
||||
# System headers will track gcc's needs.
|
||||
# Even LANG_EXTRA_HEADERS may be temporary.
|
||||
USER_H=$(LANG_EXTRA_HEADERS)
|
||||
|
||||
# We don't want this one either.
|
||||
INSTALL_ASSERT_H=
|
||||
|
||||
|
||||
|
||||
CROSS_LIBGCC1 = libgcc1-asm.a
|
||||
LIBGCC1 = libgcc1-asm.a
|
||||
|
||||
LIB1ASMSRC = alpha/lib1funcs.asm
|
||||
LIB1ASMFUNCS = _divqu _divq _divlu _divl _remqu _remq _remlu _reml
|
@ -439,10 +439,6 @@ extern int vms_valid_decl_attribute_p ();
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
fprintf (FILE, "\t.align %d\n", LOG);
|
||||
|
||||
#define UNALIGNED_SHORT_ASM_OP ".word"
|
||||
#define UNALIGNED_INT_ASM_OP ".long"
|
||||
#define UNALIGNED_DOUBLE_INT_ASM_OP ".quad"
|
||||
|
||||
#define ASM_OUTPUT_SECTION(FILE,SECTION) \
|
||||
(strcmp (SECTION, ".text") == 0) \
|
||||
? text_section () \
|
||||
|
@ -36,11 +36,11 @@ Boston, MA 02111-1307, USA. */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC ""
|
||||
|
||||
/* VxWorks uses object files, not loadable images. make linker just
|
||||
combine objects. */
|
||||
/* VxWorks uses object files, not loadable images. Make linker just combine
|
||||
objects. Also show using 32 bit mode and set start of text to 0. */
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-r"
|
||||
#define LINK_SPEC "-r -taso -T 0"
|
||||
|
||||
/* VxWorks provides the functionality of crt0.o and friends itself. */
|
||||
|
||||
|
45
contrib/gcc/config/alpha/xm-alpha-interix.h
Normal file
45
contrib/gcc/config/alpha/xm-alpha-interix.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* Configuration for GNU compiler
|
||||
for an DEC/Compaq Alpha
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
Donn Terry, Softway Systems, Inc.
|
||||
derived from code by Douglas B. Rupp (drupp@cs.washington.edu)
|
||||
|
||||
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. */
|
||||
|
||||
#include <alpha/xm-alpha.h>
|
||||
|
||||
#undef HOST_BITS_PER_LONG
|
||||
#define HOST_BITS_PER_LONG 32
|
||||
|
||||
#define HOST_BITS_PER_WIDE_INT 64
|
||||
#ifdef __GNUC__
|
||||
# define HOST_WIDE_INT long long
|
||||
#else
|
||||
# define HOST_WIDE_INT __int64
|
||||
#endif
|
||||
|
||||
|
||||
#define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_LONGLONG
|
||||
#ifdef __GNUC__
|
||||
# define HOST_WIDEST_INT long long
|
||||
#else
|
||||
# define HOST_WIDEST_INT __int64
|
||||
#endif
|
||||
#define HOST_WIDEST_INT_PRINT_DEC "%lld"
|
||||
#define HOST_WIDEST_INT_PRINT_UNSIGNED "%llu"
|
||||
#define HOST_WIDEST_INT_PRINT_HEX "0x%llx"
|
@ -46,7 +46,7 @@ Boston, MA 02111-1307, USA. */
|
||||
#if defined(__GNUC__) && !defined(USE_C_ALLOCA)
|
||||
#define alloca __builtin_alloca
|
||||
#else
|
||||
#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS)
|
||||
#if !defined(_WIN32) && !defined(USE_C_ALLOCA) && !defined(OPEN_VMS) && !defined(__INTERIX)
|
||||
#include <alloca.h>
|
||||
#else
|
||||
extern void *alloca ();
|
||||
|
@ -49,8 +49,8 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
|
||||
fprintf (FILE, \
|
||||
"\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO)
|
||||
asm_fprintf (FILE, \
|
||||
"\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
|
||||
|
||||
/* Like block addresses, stabs line numbers are relative to the
|
||||
current function. */
|
||||
|
109
contrib/gcc/config/dbxelf.h
Normal file
109
contrib/gcc/config/dbxelf.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* Definitions needed when using stabs embedded in ELF sections.
|
||||
Copyright (C) 1999 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. */
|
||||
|
||||
/* This file may be included by any ELF target which wishes to
|
||||
support -gstabs generating stabs in sections, as produced by gas
|
||||
and understood by gdb. */
|
||||
|
||||
#ifndef __DBX_ELF_H
|
||||
#define __DBX_ELF_H
|
||||
|
||||
/* Output DBX (stabs) debugging information if doing -gstabs. */
|
||||
|
||||
#undef DBX_DEBUGGING_INFO
|
||||
#define DBX_DEBUGGING_INFO
|
||||
|
||||
/* Make LBRAC and RBRAC addresses relative to the start of the
|
||||
function. The native Solaris stabs debugging format works this
|
||||
way, gdb expects it, and it reduces the number of relocation
|
||||
entries... */
|
||||
|
||||
#undef DBX_BLOCKS_FUNCTION_RELATIVE
|
||||
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
|
||||
|
||||
/* ... but, to make this work, functions must appear prior to line info. */
|
||||
|
||||
#undef DBX_FUNCTION_FIRST
|
||||
#define DBX_FUNCTION_FIRST
|
||||
|
||||
/* When generating stabs debugging, use N_BINCL entries. */
|
||||
|
||||
#undef DBX_USE_BINCL
|
||||
#define DBX_USE_BINCL
|
||||
|
||||
/* There is no limit to the length of stabs strings. */
|
||||
|
||||
#ifndef DBX_CONTIN_LENGTH
|
||||
#define DBX_CONTIN_LENGTH 0
|
||||
#endif
|
||||
|
||||
/* When using stabs, gcc2_compiled must be a stabs entry, not an
|
||||
ordinary symbol, or gdb won't see it. Furthermore, since gdb reads
|
||||
the input piecemeal, starting with each N_SO, it's a lot easier if
|
||||
the gcc2 flag symbol is *after* the N_SO rather than before it. So
|
||||
we emit an N_OPT stab there. */
|
||||
|
||||
#define ASM_IDENTIFY_GCC(FILE) \
|
||||
do \
|
||||
{ \
|
||||
if (write_symbols != DBX_DEBUG) \
|
||||
fputs ("gcc2_compiled.:\n", FILE); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define ASM_IDENTIFY_GCC_AFTER_SOURCE(FILE) \
|
||||
do \
|
||||
{ \
|
||||
if (write_symbols == DBX_DEBUG) \
|
||||
fputs ("\t.stabs\t\"gcc2_compiled.\", 0x3c, 0, 0, 0\n", FILE); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Like block addresses, stabs line numbers are relative to the
|
||||
current function. */
|
||||
|
||||
#undef ASM_OUTPUT_SOURCE_LINE
|
||||
#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
|
||||
do \
|
||||
{ \
|
||||
static int sym_lineno = 1; \
|
||||
char temp[256]; \
|
||||
ASM_GENERATE_INTERNAL_LABEL (temp, "LM", sym_lineno); \
|
||||
fprintf (FILE, ".stabn 68,0,%d,", LINE); \
|
||||
assemble_name (FILE, temp); \
|
||||
putc ('-', FILE); \
|
||||
assemble_name (FILE, \
|
||||
XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
|
||||
putc ('\n', FILE); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, "LM", sym_lineno); \
|
||||
sym_lineno += 1; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Generate a blank trailing N_SO to mark the end of the .o file, since
|
||||
we can't depend upon the linker to mark .o file boundaries with
|
||||
embedded stabs. */
|
||||
|
||||
#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
|
||||
asm_fprintf (FILE, \
|
||||
"\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
|
||||
|
||||
#endif /* __DBX_ELF_H */
|
704
contrib/gcc/config/elfos.h
Normal file
704
contrib/gcc/config/elfos.h
Normal file
@ -0,0 +1,704 @@
|
||||
/* elfos.h -- operating system specific defines to be used when
|
||||
targeting GCC for some generic ELF system
|
||||
Copyright (C) 1991, 1994, 1995, 1999 Free Software Foundation, Inc.
|
||||
Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com).
|
||||
|
||||
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. */
|
||||
|
||||
/* For the sake of libgcc2.c, indicate target supports atexit. */
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "crtend.o%s"
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{!shared: \
|
||||
%{!symbolic: \
|
||||
%{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\
|
||||
crtbegin.o%s"
|
||||
|
||||
/* Attach a special .ident directive to the end of the file to identify
|
||||
the version of GCC which compiled this code. The format of the
|
||||
.ident string is patterned after the ones produced by native svr4
|
||||
C compilers. */
|
||||
|
||||
#define IDENT_ASM_OP ".ident"
|
||||
|
||||
#define ASM_FILE_END(FILE) \
|
||||
do { \
|
||||
if (!flag_no_ident) \
|
||||
fprintf ((FILE), "\t%s\t\"GCC: (GNU) %s\"\n", \
|
||||
IDENT_ASM_OP, version_string); \
|
||||
} while (0)
|
||||
|
||||
/* Output #ident as a .ident. */
|
||||
|
||||
#define ASM_OUTPUT_IDENT(FILE, NAME) \
|
||||
fprintf (FILE, "\t%s\t\"%s\"\n", IDENT_ASM_OP, NAME);
|
||||
|
||||
/* Use periods rather than dollar signs in special g++ assembler names. */
|
||||
|
||||
#define NO_DOLLAR_IN_LABEL
|
||||
|
||||
/* Writing `int' for a bitfield forces int alignment for the structure. */
|
||||
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
|
||||
/* Implicit library calls should use memcpy, not bcopy, etc. */
|
||||
|
||||
#define TARGET_MEM_FUNCTIONS
|
||||
|
||||
/* Handle #pragma weak and #pragma pack. */
|
||||
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
|
||||
/* System V Release 4 uses DWARF debugging info. */
|
||||
|
||||
#define DWARF_DEBUGGING_INFO
|
||||
|
||||
/* All ELF targets can support DWARF-2. */
|
||||
|
||||
#define DWARF2_DEBUGGING_INFO
|
||||
|
||||
/* Also allow them to support STABS debugging. */
|
||||
|
||||
#include "dbxelf.h"
|
||||
|
||||
/* The GNU tools operate better with stabs. Since we don't have
|
||||
any native tools to be compatible with, default to stabs. */
|
||||
|
||||
#ifndef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
#endif
|
||||
|
||||
#undef ASM_BYTE_OP
|
||||
#define ASM_BYTE_OP ".byte"
|
||||
|
||||
#undef SET_ASM_OP
|
||||
#define SET_ASM_OP ".set"
|
||||
|
||||
/* This is how to begin an assembly language file. Most svr4 assemblers want
|
||||
at least a .file directive to come first, and some want to see a .version
|
||||
directive come right after that. Here we just establish a default
|
||||
which generates only the .file directive. If you need a .version
|
||||
directive for any specific target, you should override this definition
|
||||
in the target-specific file which includes this one. */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
output_file_directive ((FILE), main_input_filename)
|
||||
|
||||
/* This is how to allocate empty space in some section. The .zero
|
||||
pseudo-op is used for this on most svr4 assemblers. */
|
||||
|
||||
#define SKIP_ASM_OP ".zero"
|
||||
|
||||
#undef ASM_OUTPUT_SKIP
|
||||
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
|
||||
fprintf (FILE, "\t%s\t%u\n", SKIP_ASM_OP, (SIZE))
|
||||
|
||||
/* This is how to output a reference to a user-level label named NAME.
|
||||
`assemble_name' uses this.
|
||||
|
||||
For System V Release 4 the convention is *not* to prepend a leading
|
||||
underscore onto user-level symbol names. */
|
||||
|
||||
#undef ASM_OUTPUT_LABELREF
|
||||
#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME)
|
||||
|
||||
/* This is how to output an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
|
||||
For most svr4 systems, the convention is that any symbol which begins
|
||||
with a period is not put into the linker symbol table by the assembler. */
|
||||
|
||||
#undef ASM_OUTPUT_INTERNAL_LABEL
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL(FILE, PREFIX, NUM) \
|
||||
do { \
|
||||
fprintf (FILE, ".%s%d:\n", PREFIX, NUM); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to store into the string LABEL
|
||||
the symbol_ref name of an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
This is suitable for output with `assemble_name'.
|
||||
|
||||
For most svr4 systems, the convention is that any symbol which begins
|
||||
with a period is not put into the linker symbol table by the assembler. */
|
||||
|
||||
#undef ASM_GENERATE_INTERNAL_LABEL
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \
|
||||
do { \
|
||||
sprintf (LABEL, "*.%s%d", PREFIX, NUM); \
|
||||
} while (0)
|
||||
|
||||
/* Output the label which precedes a jumptable. Note that for all svr4
|
||||
systems where we actually generate jumptables (which is to say every
|
||||
svr4 target except i386, where we use casesi instead) we put the jump-
|
||||
tables into the .rodata section and since other stuff could have been
|
||||
put into the .rodata section prior to any given jumptable, we have to
|
||||
make sure that the location counter for the .rodata section gets pro-
|
||||
perly re-aligned prior to the actual beginning of the jump table. */
|
||||
|
||||
#define ALIGN_ASM_OP ".align"
|
||||
|
||||
#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
|
||||
#define ASM_OUTPUT_BEFORE_CASE_LABEL(FILE,PREFIX,NUM,TABLE) \
|
||||
ASM_OUTPUT_ALIGN ((FILE), 2);
|
||||
#endif
|
||||
|
||||
#undef ASM_OUTPUT_CASE_LABEL
|
||||
#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \
|
||||
do { \
|
||||
ASM_OUTPUT_BEFORE_CASE_LABEL (FILE, PREFIX, NUM, JUMPTABLE) \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM); \
|
||||
} while (0)
|
||||
|
||||
/* The standard SVR4 assembler seems to require that certain builtin
|
||||
library routines (e.g. .udiv) be explicitly declared as .globl
|
||||
in each assembly file where they are referenced. */
|
||||
|
||||
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
|
||||
ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0))
|
||||
|
||||
/* This says how to output assembler code to declare an
|
||||
uninitialized external linkage data object. Under SVR4,
|
||||
the linker seems to want the alignment of data objects
|
||||
to depend on their types. We do exactly that here. */
|
||||
|
||||
#define COMMON_ASM_OP ".comm"
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_COMMON
|
||||
#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
|
||||
do { \
|
||||
fprintf ((FILE), "\t%s\t", COMMON_ASM_OP); \
|
||||
assemble_name ((FILE), (NAME)); \
|
||||
fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
|
||||
} while (0)
|
||||
|
||||
/* This says how to output assembler code to declare an
|
||||
uninitialized internal linkage data object. Under SVR4,
|
||||
the linker seems to want the alignment of data objects
|
||||
to depend on their types. We do exactly that here. */
|
||||
|
||||
#define LOCAL_ASM_OP ".local"
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_LOCAL
|
||||
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
|
||||
do { \
|
||||
fprintf ((FILE), "\t%s\t", LOCAL_ASM_OP); \
|
||||
assemble_name ((FILE), (NAME)); \
|
||||
fprintf ((FILE), "\n"); \
|
||||
ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \
|
||||
} while (0)
|
||||
|
||||
/* This is the pseudo-op used to generate a 32-bit word of data with a
|
||||
specific value in some section. This is the same for all known svr4
|
||||
assemblers. */
|
||||
|
||||
#define INT_ASM_OP ".long"
|
||||
|
||||
/* This is the pseudo-op used to generate a contiguous sequence of byte
|
||||
values from a double-quoted string WITHOUT HAVING A TERMINATING NUL
|
||||
AUTOMATICALLY APPENDED. This is the same for most svr4 assemblers. */
|
||||
|
||||
#undef ASCII_DATA_ASM_OP
|
||||
#define ASCII_DATA_ASM_OP ".ascii"
|
||||
|
||||
/* Support const sections and the ctors and dtors sections for g++.
|
||||
Note that there appears to be two different ways to support const
|
||||
sections at the moment. You can either #define the symbol
|
||||
READONLY_DATA_SECTION (giving it some code which switches to the
|
||||
readonly data section) or else you can #define the symbols
|
||||
EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
|
||||
SELECT_RTX_SECTION. We do both here just to be on the safe side. */
|
||||
|
||||
#define USE_CONST_SECTION 1
|
||||
|
||||
#define CONST_SECTION_ASM_OP ".section\t.rodata"
|
||||
|
||||
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
|
||||
|
||||
Note that we want to give these sections the SHF_WRITE attribute
|
||||
because these sections will actually contain data (i.e. tables of
|
||||
addresses of functions in the current root executable or shared library
|
||||
file) and, in the case of a shared library, the relocatable addresses
|
||||
will have to be properly resolved/relocated (and then written into) by
|
||||
the dynamic linker when it actually attaches the given shared library
|
||||
to the executing process. (Note that on SVR4, you may wish to use the
|
||||
`-z text' option to the ELF linker, when building a shared library, as
|
||||
an additional check that you are doing everything right. But if you do
|
||||
use the `-z text' option when building a shared library, you will get
|
||||
errors unless the .ctors and .dtors sections are marked as writable
|
||||
via the SHF_WRITE attribute.) */
|
||||
|
||||
#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
|
||||
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
|
||||
|
||||
/* On svr4, we *do* have support for the .init and .fini sections, and we
|
||||
can put stuff in there to be executed before and after `main'. We let
|
||||
crtstuff.c and other files know this by defining the following symbols.
|
||||
The definitions say how to change sections to the .init and .fini
|
||||
sections. This is the same for all known svr4 assemblers. */
|
||||
|
||||
#define INIT_SECTION_ASM_OP ".section\t.init"
|
||||
#define FINI_SECTION_ASM_OP ".section\t.fini"
|
||||
|
||||
/* A default list of other sections which we might be "in" at any given
|
||||
time. For targets that use additional sections (e.g. .tdesc) you
|
||||
should override this definition in the target-specific file which
|
||||
includes this file. */
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
|
||||
|
||||
/* A default list of extra section function definitions. For targets
|
||||
that use additional sections (e.g. .tdesc) you should override this
|
||||
definition in the target-specific file which includes this file. */
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CONST_SECTION_FUNCTION \
|
||||
CTORS_SECTION_FUNCTION \
|
||||
DTORS_SECTION_FUNCTION
|
||||
|
||||
#define READONLY_DATA_SECTION() const_section ()
|
||||
|
||||
extern void text_section ();
|
||||
|
||||
#define CONST_SECTION_FUNCTION \
|
||||
void \
|
||||
const_section () \
|
||||
{ \
|
||||
if (!USE_CONST_SECTION) \
|
||||
text_section(); \
|
||||
else if (in_section != in_const) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
|
||||
in_section = in_const; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
ctors_section () \
|
||||
{ \
|
||||
if (in_section != in_ctors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
|
||||
in_section = in_ctors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
dtors_section () \
|
||||
{ \
|
||||
if (in_section != in_dtors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
|
||||
in_section = in_dtors; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Switch into a generic section.
|
||||
This is currently only used to support section attributes. */
|
||||
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
|
||||
do { \
|
||||
static struct section_info \
|
||||
{ \
|
||||
struct section_info *next; \
|
||||
char *name; \
|
||||
enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
|
||||
} *sections; \
|
||||
struct section_info *s; \
|
||||
char *mode; \
|
||||
enum sect_enum type; \
|
||||
\
|
||||
for (s = sections; s; s = s->next) \
|
||||
if (!strcmp (NAME, s->name)) \
|
||||
break; \
|
||||
\
|
||||
if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
type = SECT_EXEC, mode = "ax"; \
|
||||
else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
type = SECT_RO, mode = "a"; \
|
||||
else \
|
||||
type = SECT_RW, mode = "aw"; \
|
||||
\
|
||||
if (s == 0) \
|
||||
{ \
|
||||
s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
|
||||
s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
|
||||
strcpy (s->name, NAME); \
|
||||
s->type = type; \
|
||||
s->next = sections; \
|
||||
sections = s; \
|
||||
fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (DECL && s->type != type) \
|
||||
error_with_decl (DECL, "%s causes a section type conflict"); \
|
||||
\
|
||||
fprintf (FILE, ".section\t%s\n", NAME); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
|
||||
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
|
||||
#define UNIQUE_SECTION(DECL,RELOC) \
|
||||
do { \
|
||||
int len; \
|
||||
char *name, *string, *prefix; \
|
||||
\
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
|
||||
\
|
||||
if (! DECL_ONE_ONLY (DECL)) \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".text."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".rodata."; \
|
||||
else \
|
||||
prefix = ".data."; \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".gnu.linkonce.t."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".gnu.linkonce.r."; \
|
||||
else \
|
||||
prefix = ".gnu.linkonce.d."; \
|
||||
\
|
||||
len = strlen (name) + strlen (prefix); \
|
||||
string = alloca (len + 1); \
|
||||
sprintf (string, "%s%s", prefix, name); \
|
||||
\
|
||||
DECL_SECTION_NAME (DECL) = build_string (len, string); \
|
||||
} while (0)
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global constructors. */
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global destructors. */
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement or statements to switch to the appropriate
|
||||
section for output of DECL. DECL is either a `VAR_DECL' node
|
||||
or a constant of some sort. RELOC indicates whether forming
|
||||
the initial value of DECL requires link-time relocations. */
|
||||
|
||||
#define SELECT_SECTION(DECL,RELOC) \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == STRING_CST) \
|
||||
{ \
|
||||
if (! flag_writable_strings) \
|
||||
const_section (); \
|
||||
else \
|
||||
data_section (); \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == VAR_DECL) \
|
||||
{ \
|
||||
if ((flag_pic && RELOC) \
|
||||
|| !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
|
||||
|| !DECL_INITIAL (DECL) \
|
||||
|| (DECL_INITIAL (DECL) != error_mark_node \
|
||||
&& !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
|
||||
data_section (); \
|
||||
else \
|
||||
const_section (); \
|
||||
} \
|
||||
else \
|
||||
const_section (); \
|
||||
}
|
||||
|
||||
/* A C statement or statements to switch to the appropriate
|
||||
section for output of RTX in mode MODE. RTX is some kind
|
||||
of constant in RTL. The argument MODE is redundant except
|
||||
in the case of a `const_int' rtx. Currently, these always
|
||||
go into the const section. */
|
||||
|
||||
#undef SELECT_RTX_SECTION
|
||||
#define SELECT_RTX_SECTION(MODE,RTX) const_section()
|
||||
|
||||
/* Define the strings used for the special svr4 .type and .size directives.
|
||||
These strings generally do not vary from one system running svr4 to
|
||||
another, but if a given system (e.g. m88k running svr) needs to use
|
||||
different pseudo-op names for these, they may be overridden in the
|
||||
file which includes this one. */
|
||||
|
||||
#define TYPE_ASM_OP ".type"
|
||||
#define SIZE_ASM_OP ".size"
|
||||
|
||||
/* This is how we tell the assembler that a symbol is weak. */
|
||||
|
||||
#define ASM_WEAKEN_LABEL(FILE,NAME) \
|
||||
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
|
||||
fputc ('\n', FILE); } while (0)
|
||||
|
||||
/* The following macro defines the format used to output the second
|
||||
operand of the .type assembler directive. Different svr4 assemblers
|
||||
expect various different forms for this operand. The one given here
|
||||
is just a default. You may need to override it in your machine-
|
||||
specific tm.h file (depending upon the particulars of your assembler). */
|
||||
|
||||
#define TYPE_OPERAND_FMT "@%s"
|
||||
|
||||
/* Write the extra assembler code needed to declare a function's result.
|
||||
Most svr4 assemblers don't require any special declaration of the
|
||||
result value, but there are exceptions. */
|
||||
|
||||
#ifndef ASM_DECLARE_RESULT
|
||||
#define ASM_DECLARE_RESULT(FILE, RESULT)
|
||||
#endif
|
||||
|
||||
/* These macros generate the special .type and .size directives which
|
||||
are used to set the corresponding fields of the linker symbol table
|
||||
entries in an ELF object file under SVR4. These macros also output
|
||||
the starting labels for the relevant functions/objects. */
|
||||
|
||||
/* Write the extra assembler code needed to declare a function properly.
|
||||
Some svr4 assemblers need to also have something extra said about the
|
||||
function's return value. We allow for that here. */
|
||||
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do { \
|
||||
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
|
||||
putc ('\n', FILE); \
|
||||
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} while (0)
|
||||
|
||||
/* Write the extra assembler code needed to declare an object properly. */
|
||||
|
||||
#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \
|
||||
do { \
|
||||
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "object"); \
|
||||
putc ('\n', FILE); \
|
||||
size_directive_output = 0; \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
} \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} while (0)
|
||||
|
||||
/* Output the size directive for a decl in rest_of_decl_compilation
|
||||
in the case where we did not do so before the initializer.
|
||||
Once we find the error_mark_node, we know that the value of
|
||||
size_directive_output was set
|
||||
by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */
|
||||
|
||||
#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \
|
||||
do { \
|
||||
char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
|
||||
if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \
|
||||
&& ! AT_END && TOP_LEVEL \
|
||||
&& DECL_INITIAL (DECL) == error_mark_node \
|
||||
&& !size_directive_output) \
|
||||
{ \
|
||||
size_directive_output = 1; \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, name); \
|
||||
fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* This is how to declare the size of a function. */
|
||||
|
||||
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
|
||||
do { \
|
||||
if (!flag_inhibit_size_directive) \
|
||||
{ \
|
||||
char label[256]; \
|
||||
static int labelno; \
|
||||
labelno++; \
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
fprintf (FILE, ","); \
|
||||
assemble_name (FILE, label); \
|
||||
fprintf (FILE, "-"); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
|
||||
ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
|
||||
corresponds to a particular byte value [0..255]. For any
|
||||
given byte value, if the value in the corresponding table
|
||||
position is zero, the given character can be output directly.
|
||||
If the table value is 1, the byte must be output as a \ooo
|
||||
octal escape. If the tables value is anything else, then the
|
||||
byte value should be output as a \ followed by the value
|
||||
in the table. Note that we can use standard UN*X escape
|
||||
sequences for many control characters, but we don't use
|
||||
\a to represent BEL because some svr4 assemblers (e.g. on
|
||||
the i386) don't know about that. Also, we don't use \v
|
||||
since some versions of gas, such as 2.2 did not accept it. */
|
||||
|
||||
#define ESCAPES \
|
||||
"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
|
||||
|
||||
/* Some svr4 assemblers have a limit on the number of characters which
|
||||
can appear in the operand of a .string directive. If your assembler
|
||||
has such a limitation, you should define STRING_LIMIT to reflect that
|
||||
limit. Note that at least some svr4 assemblers have a limit on the
|
||||
actual number of bytes in the double-quoted string, and that they
|
||||
count each character in an escape sequence as one byte. Thus, an
|
||||
escape sequence like \377 would count as four bytes.
|
||||
|
||||
If your target assembler doesn't support the .string directive, you
|
||||
should define this to zero.
|
||||
*/
|
||||
|
||||
#define STRING_LIMIT ((unsigned) 256)
|
||||
|
||||
#define STRING_ASM_OP ".string"
|
||||
|
||||
/* The routine used to output NUL terminated strings. We use a special
|
||||
version of this for most svr4 targets because doing so makes the
|
||||
generated assembly code more compact (and thus faster to assemble)
|
||||
as well as more readable, especially for targets like the i386
|
||||
(where the only alternative is to output character sequences as
|
||||
comma separated lists of numbers). */
|
||||
|
||||
#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
|
||||
do \
|
||||
{ \
|
||||
register unsigned char *_limited_str = (unsigned char *) (STR); \
|
||||
register unsigned ch; \
|
||||
fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \
|
||||
for (; ch = *_limited_str; _limited_str++) \
|
||||
{ \
|
||||
register int escape; \
|
||||
switch (escape = ESCAPES[ch]) \
|
||||
{ \
|
||||
case 0: \
|
||||
putc (ch, (FILE)); \
|
||||
break; \
|
||||
case 1: \
|
||||
fprintf ((FILE), "\\%03o", ch); \
|
||||
break; \
|
||||
default: \
|
||||
putc ('\\', (FILE)); \
|
||||
putc (escape, (FILE)); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* The routine used to output sequences of byte values. We use a special
|
||||
version of this for most svr4 targets because doing so makes the
|
||||
generated assembly code more compact (and thus faster to assemble)
|
||||
as well as more readable. Note that if we find subparts of the
|
||||
character sequence which end with NUL (and which are shorter than
|
||||
STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
|
||||
|
||||
#undef ASM_OUTPUT_ASCII
|
||||
#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
|
||||
do \
|
||||
{ \
|
||||
register unsigned char *_ascii_bytes = (unsigned char *) (STR); \
|
||||
register unsigned char *limit = _ascii_bytes + (LENGTH); \
|
||||
register unsigned bytes_in_chunk = 0; \
|
||||
for (; _ascii_bytes < limit; _ascii_bytes++) \
|
||||
{ \
|
||||
register unsigned char *p; \
|
||||
if (bytes_in_chunk >= 60) \
|
||||
{ \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
bytes_in_chunk = 0; \
|
||||
} \
|
||||
for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
|
||||
continue; \
|
||||
if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
|
||||
{ \
|
||||
if (bytes_in_chunk > 0) \
|
||||
{ \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
bytes_in_chunk = 0; \
|
||||
} \
|
||||
ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
|
||||
_ascii_bytes = p; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
register int escape; \
|
||||
register unsigned ch; \
|
||||
if (bytes_in_chunk == 0) \
|
||||
fprintf ((FILE), "\t%s\t\"", ASCII_DATA_ASM_OP); \
|
||||
switch (escape = ESCAPES[ch = *_ascii_bytes]) \
|
||||
{ \
|
||||
case 0: \
|
||||
putc (ch, (FILE)); \
|
||||
bytes_in_chunk++; \
|
||||
break; \
|
||||
case 1: \
|
||||
fprintf ((FILE), "\\%03o", ch); \
|
||||
bytes_in_chunk += 4; \
|
||||
break; \
|
||||
default: \
|
||||
putc ('\\', (FILE)); \
|
||||
putc (escape, (FILE)); \
|
||||
bytes_in_chunk += 2; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if (bytes_in_chunk > 0) \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* All SVR4 targets use the ELF object file format. */
|
||||
#define OBJECT_FORMAT_ELF
|
@ -37,7 +37,7 @@
|
||||
#undef FLT_MAX_10_EXP
|
||||
#define FLT_MAX_10_EXP 38
|
||||
|
||||
#ifdef __SH3E__
|
||||
#if defined (__SH3E__) || defined (__SH4_SINGLE_ONLY__)
|
||||
|
||||
/* Number of base-FLT_RADIX digits in the significand of a double */
|
||||
#undef DBL_MANT_DIG
|
||||
|
@ -156,8 +156,8 @@ __floatsixf (){ abort(); }
|
||||
#else /* !EXTENDED_FLOAT_STUBS, rest of file */
|
||||
|
||||
|
||||
typedef SFtype __attribute__ ((mode (SF)));
|
||||
typedef DFtype __attribute__ ((mode (DF)));
|
||||
typedef float SFtype __attribute__ ((mode (SF)));
|
||||
typedef float DFtype __attribute__ ((mode (DF)));
|
||||
|
||||
typedef int HItype __attribute__ ((mode (HI)));
|
||||
typedef int SItype __attribute__ ((mode (SI)));
|
||||
@ -460,7 +460,6 @@ pack_d ( fp_number_type * src)
|
||||
else if (fraction == 0)
|
||||
{
|
||||
exp = 0;
|
||||
sign = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -735,7 +734,7 @@ _fpadd_parts (fp_number_type * a,
|
||||
{
|
||||
tfraction = a_fraction - b_fraction;
|
||||
}
|
||||
if (tfraction > 0)
|
||||
if (tfraction >= 0)
|
||||
{
|
||||
tmp->sign = 0;
|
||||
tmp->normal_exp = a_normal_exp;
|
||||
@ -1000,8 +999,7 @@ multiply (FLO_type arg_a, FLO_type arg_b)
|
||||
#if defined(L_div_sf) || defined(L_div_df)
|
||||
static INLINE fp_number_type *
|
||||
_fpdiv_parts (fp_number_type * a,
|
||||
fp_number_type * b,
|
||||
fp_number_type * tmp)
|
||||
fp_number_type * b)
|
||||
{
|
||||
fractype bit;
|
||||
fractype numerator;
|
||||
@ -1093,13 +1091,12 @@ divide (FLO_type arg_a, FLO_type arg_b)
|
||||
{
|
||||
fp_number_type a;
|
||||
fp_number_type b;
|
||||
fp_number_type tmp;
|
||||
fp_number_type *res;
|
||||
|
||||
unpack_d ((FLO_union_type *) & arg_a, &a);
|
||||
unpack_d ((FLO_union_type *) & arg_b, &b);
|
||||
|
||||
res = _fpdiv_parts (&a, &b, &tmp);
|
||||
res = _fpdiv_parts (&a, &b);
|
||||
|
||||
return pack_d (res);
|
||||
}
|
||||
@ -1332,7 +1329,7 @@ si_to_float (SItype arg_a)
|
||||
{
|
||||
/* Special case for minint, since there is no +ve integer
|
||||
representation for it */
|
||||
if (arg_a == 0x80000000)
|
||||
if (arg_a == (SItype) 0x80000000)
|
||||
{
|
||||
return -2147483648.0;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for IBM PS2 running AIX/386.
|
||||
Copyright (C) 1988, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1996, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Minh Tran-Le <TRANLE@intellicorp.com>.
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -58,9 +58,7 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { fprintf (FILE, "\t.file\t"); \
|
||||
output_quoted_string (FILE, dump_base_name); \
|
||||
fprintf (FILE, "\n"); \
|
||||
do { output_file_directive (FILE, main_input_filename); \
|
||||
if (optimize) \
|
||||
ASM_FILE_START_1 (FILE); \
|
||||
else \
|
||||
|
@ -49,9 +49,7 @@ Boston, MA 02111-1307, USA. */
|
||||
??? I am skeptical of this -- RMS. */
|
||||
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { fprintf (FILE, "\t.file\t"); \
|
||||
output_quoted_string (FILE, dump_base_name); \
|
||||
fprintf (FILE, "\n"); \
|
||||
do { output_file_directive (FILE, main_input_filename); \
|
||||
} while (0)
|
||||
|
||||
/* This was suggested, but it shouldn't be right for DBX output. -- RMS
|
||||
|
@ -3,7 +3,7 @@
|
||||
as distinct from winnt.h, which is used to build GCC for use with a
|
||||
windows style library and tool set and uses the Microsoft tools.
|
||||
This variant uses CRTDLL.DLL insted of MSVCRTDLL.DLL.
|
||||
Copyright (C) 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \
|
||||
-D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\
|
||||
-D__MINGW32__=0.2 -DWINNT -D_X86_=1 -D__STDC__=1\
|
||||
-D__stdcall=__attribute__((__stdcall__)) \
|
||||
-D_stdcall=__attribute__((__stdcall__)) \
|
||||
-D__cdecl=__attribute__((__cdecl__)) \
|
||||
@ -38,5 +38,3 @@ Boston, MA 02111-1307, USA. */
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{mdll:dllcrt1%O%s} %{!mdll:crt1%O%s}"
|
||||
|
||||
#undef MATH_LIBRARY
|
||||
#define MATH_LIBRARY "-lcrtdll"
|
||||
|
32
contrib/gcc/config/i386/cygwin.asm
Normal file
32
contrib/gcc/config/i386/cygwin.asm
Normal file
@ -0,0 +1,32 @@
|
||||
/* stuff needed for libgcc1 on win32. */
|
||||
|
||||
#ifdef L_chkstk
|
||||
|
||||
.global ___chkstk
|
||||
.global __alloca
|
||||
___chkstk:
|
||||
__alloca:
|
||||
pushl %ecx /* save temp */
|
||||
movl %esp,%ecx /* get sp */
|
||||
addl $0x8,%ecx /* and point to return addr */
|
||||
|
||||
probe: cmpl $0x1000,%eax /* > 4k ?*/
|
||||
jb done
|
||||
|
||||
subl $0x1000,%ecx /* yes, move pointer down 4k*/
|
||||
orl $0x0,(%ecx) /* probe there */
|
||||
subl $0x1000,%eax /* decrement count */
|
||||
jmp probe /* and do it again */
|
||||
|
||||
done: subl %eax,%ecx
|
||||
orl $0x0,(%ecx) /* less that 4k, just peek here */
|
||||
|
||||
movl %esp,%eax
|
||||
movl %ecx,%esp /* decrement stack */
|
||||
|
||||
movl (%eax),%ecx /* recover saved temp */
|
||||
movl 4(%eax),%eax /* get return address */
|
||||
jmp *%eax
|
||||
|
||||
|
||||
#endif
|
525
contrib/gcc/config/i386/cygwin.h
Normal file
525
contrib/gcc/config/i386/cygwin.h
Normal file
@ -0,0 +1,525 @@
|
||||
/* Operating system specific defines to be used when targeting GCC for
|
||||
hosting on Windows NT 3.x, using a Unix style C library and tools,
|
||||
as distinct from winnt.h, which is used to build GCC for use with a
|
||||
windows style library and tool set and uses the Microsoft tools.
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 1999 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. */
|
||||
|
||||
#define YES_UNDERSCORES
|
||||
|
||||
#define DBX_DEBUGGING_INFO
|
||||
#define SDB_DEBUGGING_INFO
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
|
||||
#include "i386/gas.h"
|
||||
#include "dbxcoff.h"
|
||||
|
||||
/* Augment TARGET_SWITCHES with the cygwin/no-cygwin options. */
|
||||
#define MASK_WIN32 0x40000000 /* Use -lming32 interface */
|
||||
#define MASK_CYGWIN 0x20000000 /* Use -lcygwin interface */
|
||||
#define MASK_WINDOWS 0x10000000 /* Use windows interface */
|
||||
#define MASK_DLL 0x08000000 /* Use dll interface */
|
||||
#define MASK_NOP_FUN_DLLIMPORT 0x20000 /* Ignore dllimport for functions */
|
||||
|
||||
#define TARGET_WIN32 (target_flags & MASK_WIN32)
|
||||
#define TARGET_CYGWIN (target_flags & MASK_CYGWIN)
|
||||
#define TARGET_WINDOWS (target_flags & MASK_WINDOWS)
|
||||
#define TARGET_DLL (target_flags & MASK_DLL)
|
||||
#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "cygwin", MASK_CYGWIN, "Use the Cygwin interface" }, \
|
||||
{ "no-cygwin", MASK_WIN32, "Use the Mingw32 interface" }, \
|
||||
{ "windows", MASK_WINDOWS, "Create GUI application" }, \
|
||||
{ "console", -MASK_WINDOWS, "Create console application" }, \
|
||||
{ "dll", MASK_DLL, "Generate code for a DLL" }, \
|
||||
{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, "Ignore dllimport for functions" }, \
|
||||
{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" },
|
||||
|
||||
|
||||
/* Support the __declspec keyword by turning them into attributes.
|
||||
We currently only support: dllimport and dllexport.
|
||||
Note that the current way we do this may result in a collision with
|
||||
predefined attributes later on. This can be solved by using one attribute,
|
||||
say __declspec__, and passing args to it. The problem with that approach
|
||||
is that args are not accumulated: each new appearance would clobber any
|
||||
existing args. */
|
||||
|
||||
#ifdef CPP_PREDEFINES
|
||||
#undef CPP_PREDEFINES
|
||||
#endif
|
||||
|
||||
#define CPP_PREDEFINES "-Di386 -D_WIN32 \
|
||||
-DWINNT -D_X86_=1 -D__STDC__=1\
|
||||
-D__stdcall=__attribute__((__stdcall__)) \
|
||||
-D__cdecl=__attribute__((__cdecl__)) \
|
||||
-D__declspec(x)=__attribute__((x)) \
|
||||
-Asystem(winnt) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
/* Normally, -lgcc is not needed since everything in it is in the DLL, but we
|
||||
want to allow things to be added to it when installing new versions of
|
||||
GCC without making a new CYGWIN.DLL, so we leave it. Profiling is handled
|
||||
by calling the init function from the prologue. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{mdll: %{mno-cygwin:dllcrt1%O%s}} \
|
||||
%{!mdll: %{!mno-cygwin:crt0%O%s} \
|
||||
%{mno-cygwin:crt1%O%s} %{pg:gcrt0%O%s}}"
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE} \
|
||||
%{!mno-cygwin:-D__CYGWIN32__ -D__CYGWIN__} \
|
||||
%{mno-cygwin:-iwithprefixbefore \
|
||||
../../../../%(mingw_include_path)/include/mingw32 -D__MINGW32__=0.2}"
|
||||
|
||||
/* This macro defines names of additional specifications to put in the specs
|
||||
that can be used in various specifications like CC1_SPEC. Its definition
|
||||
is an initializer with a subgrouping for each command option.
|
||||
|
||||
Each subgrouping contains a string constant, that defines the
|
||||
specification name, and a string constant that used by the GNU CC driver
|
||||
program.
|
||||
|
||||
Do not define this macro if it does not need to do anything. */
|
||||
|
||||
#undef SUBTARGET_EXTRA_SPECS
|
||||
#define SUBTARGET_EXTRA_SPECS \
|
||||
{ "mingw_include_path", DEFAULT_TARGET_MACHINE }
|
||||
|
||||
/* We have to dynamic link to get to the system DLLs. All of libc, libm and
|
||||
the Unix stuff is in cygwin.dll. The import library is called
|
||||
'libcygwin.a'. For Windows applications, include more libraries, but
|
||||
always include kernel32. We'd like to specific subsystem windows to
|
||||
ld, but that doesn't work just yet. */
|
||||
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "%{pg:-lgmon} \
|
||||
%{!mno-cygwin:-lcygwin} \
|
||||
%{mno-cygwin:-lmingw32 -lmoldname -lcrtdll} \
|
||||
%{mwindows:-lgdi32 -lcomdlg32} \
|
||||
-luser32 -lkernel32 -ladvapi32 -lshell32"
|
||||
|
||||
#define LINK_SPEC "%{mwindows:--subsystem windows} \
|
||||
%{mconsole:--subsystem console} \
|
||||
%{mdll:--dll -e _DllMainCRTStartup@12}"
|
||||
|
||||
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
#define PTRDIFF_TYPE "int"
|
||||
#define WCHAR_UNSIGNED 1
|
||||
#define WCHAR_TYPE_SIZE 16
|
||||
#define WCHAR_TYPE "short unsigned int"
|
||||
|
||||
#define HAVE_ATEXIT 1
|
||||
|
||||
|
||||
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
|
||||
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
|
||||
|
||||
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
|
||||
is a valid machine specific attribute for DECL.
|
||||
The attributes in ATTRIBUTES have previously been assigned to DECL. */
|
||||
extern int i386_pe_valid_decl_attribute_p ();
|
||||
|
||||
#undef VALID_MACHINE_DECL_ATTRIBUTE
|
||||
#define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
|
||||
i386_pe_valid_decl_attribute_p (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
|
||||
|
||||
/* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
|
||||
is a valid machine specific attribute for TYPE.
|
||||
The attributes in ATTRIBUTES have previously been assigned to TYPE. */
|
||||
|
||||
#undef VALID_MACHINE_TYPE_ATTRIBUTE
|
||||
#define VALID_MACHINE_TYPE_ATTRIBUTE(TYPE, ATTRIBUTES, IDENTIFIER, ARGS) \
|
||||
i386_pe_valid_type_attribute_p (TYPE, ATTRIBUTES, IDENTIFIER, ARGS)
|
||||
extern int i386_pe_valid_type_attribute_p ();
|
||||
|
||||
extern union tree_node *i386_pe_merge_decl_attributes ();
|
||||
#define MERGE_MACHINE_DECL_ATTRIBUTES(OLD, NEW) \
|
||||
i386_pe_merge_decl_attributes ((OLD), (NEW))
|
||||
|
||||
/* Used to implement dllexport overriding dllimport semantics. It's also used
|
||||
to handle vtables - the first pass won't do anything because
|
||||
DECL_CONTEXT (DECL) will be 0 so i386_pe_dll{ex,im}port_p will return 0.
|
||||
It's also used to handle dllimport override semantics. */
|
||||
#if 0
|
||||
#define REDO_SECTION_INFO_P(DECL) \
|
||||
((DECL_MACHINE_ATTRIBUTES (DECL) != NULL_TREE) \
|
||||
|| (TREE_CODE (DECL) == VAR_DECL && DECL_VIRTUAL_P (DECL)))
|
||||
#else
|
||||
#define REDO_SECTION_INFO_P(DECL) 1
|
||||
#endif
|
||||
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_ctor, in_dtor, in_drectve
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CTOR_SECTION_FUNCTION \
|
||||
DTOR_SECTION_FUNCTION \
|
||||
DRECTVE_SECTION_FUNCTION \
|
||||
SWITCH_TO_SECTION_FUNCTION
|
||||
|
||||
#define CTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
ctor_section () \
|
||||
{ \
|
||||
if (in_section != in_ctor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .ctor\n"); \
|
||||
in_section = in_ctor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
dtor_section () \
|
||||
{ \
|
||||
if (in_section != in_dtor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .dtor\n"); \
|
||||
in_section = in_dtor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DRECTVE_SECTION_FUNCTION \
|
||||
void \
|
||||
drectve_section () \
|
||||
{ \
|
||||
if (in_section != in_drectve) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", "\t.section .drectve\n"); \
|
||||
in_section = in_drectve; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Switch to SECTION (an `enum in_section').
|
||||
|
||||
??? This facility should be provided by GCC proper.
|
||||
The problem is that we want to temporarily switch sections in
|
||||
ASM_DECLARE_OBJECT_NAME and then switch back to the original section
|
||||
afterwards. */
|
||||
#define SWITCH_TO_SECTION_FUNCTION \
|
||||
void \
|
||||
switch_to_section (section, decl) \
|
||||
enum in_section section; \
|
||||
tree decl; \
|
||||
{ \
|
||||
switch (section) \
|
||||
{ \
|
||||
case in_text: text_section (); break; \
|
||||
case in_data: data_section (); break; \
|
||||
case in_named: named_section (decl, NULL, 0); break; \
|
||||
case in_ctor: ctor_section (); break; \
|
||||
case in_dtor: dtor_section (); break; \
|
||||
case in_drectve: drectve_section (); break; \
|
||||
default: abort (); break; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Don't allow flag_pic to propagate since gas may produce invalid code
|
||||
otherwise. */
|
||||
|
||||
#undef SUBTARGET_OVERRIDE_OPTIONS
|
||||
#define SUBTARGET_OVERRIDE_OPTIONS \
|
||||
do { \
|
||||
if (flag_pic) \
|
||||
{ \
|
||||
warning ("-f%s ignored for target (all code is position independent)",\
|
||||
(flag_pic > 1) ? "PIC" : "pic"); \
|
||||
flag_pic = 0; \
|
||||
} \
|
||||
} while (0) \
|
||||
|
||||
/* Define this macro if references to a symbol must be treated
|
||||
differently depending on something about the variable or
|
||||
function named by the symbol (such as what section it is in).
|
||||
|
||||
On i386 running Windows NT, modify the assembler name with a suffix
|
||||
consisting of an atsign (@) followed by string of digits that represents
|
||||
the number of bytes of arguments passed to the function, if it has the
|
||||
attribute STDCALL.
|
||||
|
||||
In addition, we must mark dll symbols specially. Definitions of
|
||||
dllexport'd objects install some info in the .drectve section.
|
||||
References to dllimport'd objects are fetched indirectly via
|
||||
_imp__. If both are declared, dllexport overrides. This is also
|
||||
needed to implement one-only vtables: they go into their own
|
||||
section and we need to set DECL_SECTION_NAME so we do that here.
|
||||
Note that we can be called twice on the same decl. */
|
||||
|
||||
extern void i386_pe_encode_section_info ();
|
||||
|
||||
#ifdef ENCODE_SECTION_INFO
|
||||
#undef ENCODE_SECTION_INFO
|
||||
#endif
|
||||
#define ENCODE_SECTION_INFO(DECL) i386_pe_encode_section_info (DECL)
|
||||
|
||||
/* Utility used only in this file. */
|
||||
#define I386_PE_STRIP_ENCODING(SYM_NAME) \
|
||||
((SYM_NAME) + ((SYM_NAME)[0] == '@' ? 3 : 0))
|
||||
|
||||
/* This macro gets just the user-specified name
|
||||
out of the string in a SYMBOL_REF. Discard
|
||||
trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
|
||||
#undef STRIP_NAME_ENCODING
|
||||
#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
|
||||
do { \
|
||||
char *_p; \
|
||||
char *_name = I386_PE_STRIP_ENCODING (SYMBOL_NAME); \
|
||||
for (_p = _name; *_p && *_p != '@'; ++_p) \
|
||||
; \
|
||||
if (*_p == '@') \
|
||||
{ \
|
||||
int _len = _p - _name; \
|
||||
(VAR) = (char *) alloca (_len + 1); \
|
||||
strncpy ((VAR), _name, _len); \
|
||||
(VAR)[_len] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
(VAR) = _name; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Output a reference to a label. */
|
||||
#undef ASM_OUTPUT_LABELREF
|
||||
#define ASM_OUTPUT_LABELREF(STREAM, NAME) \
|
||||
fprintf (STREAM, "%s%s", USER_LABEL_PREFIX, \
|
||||
I386_PE_STRIP_ENCODING (NAME)) \
|
||||
|
||||
/* Output a common block. */
|
||||
#undef ASM_OUTPUT_COMMON
|
||||
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
|
||||
do { \
|
||||
if (i386_pe_dllexport_name_p (NAME)) \
|
||||
i386_pe_record_exported_symbol (NAME); \
|
||||
if (! i386_pe_dllimport_name_p (NAME)) \
|
||||
{ \
|
||||
fprintf ((STREAM), "\t.comm\t"); \
|
||||
assemble_name ((STREAM), (NAME)); \
|
||||
fprintf ((STREAM), ", %d\t%s %d\n", \
|
||||
(ROUNDED), ASM_COMMENT_START, (SIZE)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Output the label for an initialized variable. */
|
||||
#undef ASM_DECLARE_OBJECT_NAME
|
||||
#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
|
||||
do { \
|
||||
if (i386_pe_dllexport_name_p (NAME)) \
|
||||
i386_pe_record_exported_symbol (NAME); \
|
||||
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Emit code to check the stack when allocating more that 4000
|
||||
bytes in one go. */
|
||||
|
||||
#define CHECK_STACK_LIMIT 4000
|
||||
|
||||
/* By default, target has a 80387, uses IEEE compatible arithmetic,
|
||||
and returns float values in the 387 and needs stack probes */
|
||||
#undef TARGET_DEFAULT
|
||||
|
||||
#define TARGET_DEFAULT \
|
||||
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE)
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
|
||||
|
||||
/* Define this macro if in some cases global symbols from one translation
|
||||
unit may not be bound to undefined symbols in another translation unit
|
||||
without user intervention. For instance, under Microsoft Windows
|
||||
symbols must be explicitly imported from shared libraries (DLLs). */
|
||||
#define MULTIPLE_SYMBOL_SPACES
|
||||
|
||||
#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
|
||||
extern void i386_pe_unique_section ();
|
||||
#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
|
||||
|
||||
#define SUPPORTS_ONE_ONLY 1
|
||||
|
||||
/* A C statement to output something to the assembler file to switch to section
|
||||
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
|
||||
NULL_TREE. Some target formats do not support arbitrary sections. Do not
|
||||
define this macro in such cases. */
|
||||
#undef ASM_OUTPUT_SECTION_NAME
|
||||
#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
|
||||
do { \
|
||||
static struct section_info \
|
||||
{ \
|
||||
struct section_info *next; \
|
||||
char *name; \
|
||||
enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
|
||||
} *sections; \
|
||||
struct section_info *s; \
|
||||
char *mode; \
|
||||
enum sect_enum type; \
|
||||
\
|
||||
for (s = sections; s; s = s->next) \
|
||||
if (!strcmp (NAME, s->name)) \
|
||||
break; \
|
||||
\
|
||||
if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
type = SECT_EXEC, mode = "x"; \
|
||||
else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
type = SECT_RO, mode = ""; \
|
||||
else \
|
||||
type = SECT_RW, mode = "w"; \
|
||||
\
|
||||
if (s == 0) \
|
||||
{ \
|
||||
s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
|
||||
s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
|
||||
strcpy (s->name, NAME); \
|
||||
s->type = type; \
|
||||
s->next = sections; \
|
||||
sections = s; \
|
||||
fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
|
||||
/* Functions may have been compiled at various levels of \
|
||||
optimization so we can't use `same_size' here. Instead, \
|
||||
have the linker pick one. */ \
|
||||
if ((DECL) && DECL_ONE_ONLY (DECL)) \
|
||||
fprintf (STREAM, "\t.linkonce %s\n", \
|
||||
TREE_CODE (DECL) == FUNCTION_DECL \
|
||||
? "discard" : "same_size"); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Write the extra assembler code needed to declare a function
|
||||
properly. If we are generating SDB debugging information, this
|
||||
will happen automatically, so we only need to handle other cases. */
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
if (i386_pe_dllexport_name_p (NAME)) \
|
||||
i386_pe_record_exported_symbol (NAME); \
|
||||
if (write_symbols != SDB_DEBUG) \
|
||||
i386_pe_declare_function_type (FILE, NAME, TREE_PUBLIC (DECL)); \
|
||||
ASM_OUTPUT_LABEL (FILE, NAME); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Add an external function to the list of functions to be declared at
|
||||
the end of the file. */
|
||||
#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
|
||||
do \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
i386_pe_record_external_function (NAME); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Declare the type properly for any external libcall. */
|
||||
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \
|
||||
i386_pe_declare_function_type (FILE, XSTR (FUN, 0), 1)
|
||||
|
||||
/* Output function declarations at the end of the file. */
|
||||
#define ASM_FILE_END(FILE) \
|
||||
i386_pe_asm_file_end (FILE)
|
||||
|
||||
#undef ASM_COMMENT_START
|
||||
#define ASM_COMMENT_START " #"
|
||||
|
||||
/* DWARF2 Unwinding doesn't work with exception handling yet. */
|
||||
#define DWARF2_UNWIND_INFO 0
|
||||
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
#define SUBTARGET_PROLOGUE \
|
||||
if (profile_flag \
|
||||
&& strcmp (IDENTIFIER_POINTER (DECL_NAME (current_function_decl)),\
|
||||
"main") == 0) \
|
||||
{ \
|
||||
rtx xops[1]; \
|
||||
xops[0] = gen_rtx_MEM (FUNCTION_MODE, \
|
||||
gen_rtx (SYMBOL_REF, Pmode, "_monstartup")); \
|
||||
if (do_rtl) \
|
||||
emit_call_insn (gen_rtx (CALL, VOIDmode, xops[0], const0_rtx)); \
|
||||
else \
|
||||
output_asm_insn (AS1 (call,%P1), xops); \
|
||||
}
|
||||
|
||||
/* External function declarations. */
|
||||
|
||||
#ifndef PROTO
|
||||
#if defined (USE_PROTOTYPES) ? USE_PROTOTYPES : defined (__STDC__)
|
||||
#define PROTO(ARGS) ARGS
|
||||
#else
|
||||
#define PROTO(ARGS) ()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BUFSIZ /* stdio.h has been included, ok to use FILE * */
|
||||
#define STDIO_PROTO(ARGS) PROTO(ARGS)
|
||||
#else
|
||||
#define STDIO_PROTO(ARGS) ()
|
||||
#endif
|
||||
|
||||
extern void i386_pe_record_external_function PROTO((char *));
|
||||
extern void i386_pe_declare_function_type STDIO_PROTO((FILE *, char *, int));
|
||||
extern void i386_pe_record_exported_symbol PROTO((char *));
|
||||
extern void i386_pe_asm_file_end STDIO_PROTO((FILE *));
|
||||
|
||||
/* For Win32 ABI compatibility */
|
||||
#undef DEFAULT_PCC_STRUCT_RETURN
|
||||
#define DEFAULT_PCC_STRUCT_RETURN 0
|
||||
|
||||
/* No data type wants to be aligned rounder than this. */
|
||||
#undef BIGGEST_ALIGNMENT
|
||||
#define BIGGEST_ALIGNMENT 128
|
||||
|
||||
/* A bitfield declared as `int' forces `int' alignment for the struct. */
|
||||
#undef PCC_BITFIELDS_TYPE_MATTERS
|
||||
#define PCC_BITFIELDS_TYPE_MATTERS 0
|
||||
|
||||
/* Enable alias attribute support. */
|
||||
#ifndef SET_ASM_OP
|
||||
#define SET_ASM_OP "\t.set"
|
||||
#endif
|
||||
|
@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <time.h>
|
||||
#include "i386/i386.c"
|
||||
@ -29,6 +30,7 @@ struct option
|
||||
char *string;
|
||||
int *variable;
|
||||
int on_value;
|
||||
char *description;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* for now, we are just like the sysv4 version with a
|
||||
few hacks
|
||||
@ -25,7 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#include "i386/sysv4.h"
|
||||
|
||||
#ifndef VERSION_INFO2
|
||||
#define VERSION_INFO2 "$Revision: 1.3 $"
|
||||
#define VERSION_INFO2 "$Revision: 1.6 $"
|
||||
#endif
|
||||
|
||||
#ifndef VERSION_STRING
|
||||
@ -46,7 +47,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
#define MASK_NOLEGEND 0x20000000 /* Discard legend information */
|
||||
#define MASK_EXTERNAL_LEGEND 0x10000000 /* Make external legends */
|
||||
#define MASK_IDENTIFY_REVISION 0x08000000 /* Emit 'ident' to .s */
|
||||
#define MASK_WARN_PASS_STRUCT 0x04000000 /* Emit 'ident' to .s */
|
||||
#define MASK_WARN_PASS_STRUCT 0x04000000 /* Warn when structures are passed */
|
||||
|
||||
#define TARGET_STANDARD (target_flags & MASK_STANDARD)
|
||||
#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND)
|
||||
@ -56,12 +57,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "standard", MASK_STANDARD }, \
|
||||
{ "legend", -MASK_NOLEGEND }, \
|
||||
{ "no-legend", MASK_NOLEGEND }, \
|
||||
{ "external-legend", MASK_EXTERNAL_LEGEND }, \
|
||||
{ "identify-revision", MASK_IDENTIFY_REVISION }, \
|
||||
{ "warn-passed-structs", MASK_WARN_PASS_STRUCT },
|
||||
{ "standard", MASK_STANDARD, "Retain standard MXDB information" }, \
|
||||
{ "legend", -MASK_NOLEGEND, "Retain legend information" }, \
|
||||
{ "no-legend", MASK_NOLEGEND, "" }, \
|
||||
{ "external-legend", MASK_EXTERNAL_LEGEND, "Generate external legend information" }, \
|
||||
{ "identify-revision", MASK_IDENTIFY_REVISION, "Emit identifying info in .s file" }, \
|
||||
{ "warn-passed-structs", MASK_WARN_PASS_STRUCT, "Warn when a function arg is a structure" },
|
||||
|
||||
#undef DWARF_DEBUGGING_INFO
|
||||
#define DWARF_DEBUGGING_INFO
|
||||
@ -123,7 +124,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
do { \
|
||||
extern int flag_signed_bitfields; \
|
||||
flag_signed_bitfields = 0; \
|
||||
abort_helper (); \
|
||||
optimization_options (LEVEL,SIZE); \
|
||||
} while (0)
|
||||
|
||||
@ -219,23 +219,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#endif /* CROSS_COMPILE */
|
||||
|
||||
#if !defined (no_abort) || defined (CRT_BEGIN) || defined (CRT_END)
|
||||
#undef abort
|
||||
|
||||
char insn; int insn_; char * file_; int line_;
|
||||
#define abort() \
|
||||
(insn_ = (int) insn, \
|
||||
file_ = __FILE__, \
|
||||
line_ = __LINE__, \
|
||||
fancy_abort ())
|
||||
#define abort_helper() \
|
||||
do { \
|
||||
extern void abort_aux (); \
|
||||
atexit (abort_aux); \
|
||||
} while (0)
|
||||
#define _abort_aux
|
||||
#endif /* no abort */
|
||||
|
||||
/* The maximum alignment which the object file format can support.
|
||||
page alignment would seem to be enough */
|
||||
#undef MAX_OFILE_ALIGNMENT
|
||||
|
41
contrib/gcc/config/i386/djgpp-rtems.h
Normal file
41
contrib/gcc/config/i386/djgpp-rtems.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* Configuration for an i386 running RTEMS on top of MS-DOS with
|
||||
DJGPP v2.x.
|
||||
|
||||
Copyright (C) 1996,1999 Free Software Foundation, Inc.
|
||||
Contributed by Joel Sherrill (joel@OARcorp.com).
|
||||
|
||||
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. */
|
||||
|
||||
#include "i386/djgpp.h"
|
||||
|
||||
/* Specify predefined symbols in preprocessor. */
|
||||
|
||||
#ifdef CPP_PREDEFINES
|
||||
#undef CPP_PREDEFINES
|
||||
#endif
|
||||
#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DDJGPP=2 -DMSDOS \
|
||||
-Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386) \
|
||||
-Asystem(rtems)"
|
||||
|
||||
/* Generate calls to memcpy, memcmp and memset. */
|
||||
#ifndef TARGET_MEM_FUNCTIONS
|
||||
#define TARGET_MEM_FUNCTIONS
|
||||
#endif
|
||||
|
||||
/* end of i386/djgpp-rtems.h */
|
||||
|
161
contrib/gcc/config/i386/djgpp.h
Normal file
161
contrib/gcc/config/i386/djgpp.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* Configuration for an i386 running MS-DOS with DJGPP.
|
||||
Copyright (C) 1997, 1998, 1999 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. */
|
||||
|
||||
|
||||
#include "dbxcoff.h"
|
||||
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
|
||||
/* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop). */
|
||||
#define HANDLE_PRAGMA_PACK_PUSH_POP 1
|
||||
|
||||
#define YES_UNDERSCORES
|
||||
|
||||
#include "i386/gas.h"
|
||||
|
||||
/* Enable alias attribute support. */
|
||||
#ifndef SET_ASM_OP
|
||||
#define SET_ASM_OP "\t.set"
|
||||
#endif
|
||||
|
||||
/* Search for as.exe and ld.exe in DJGPP's binary directory. */
|
||||
#define MD_EXEC_PREFIX "$DJDIR/bin/"
|
||||
|
||||
/* Correctly handle absolute filename detection in cp/xref.c */
|
||||
#define FILE_NAME_ABSOLUTE_P(NAME) \
|
||||
(((NAME)[0] == '/') || ((NAME)[0] == '\\') || \
|
||||
(((NAME)[0] >= 'A') && ((NAME)[0] <= 'z') && ((NAME)[1] == ':')))
|
||||
|
||||
#ifdef CPP_PREDEFINES
|
||||
#undef CPP_PREDEFINES
|
||||
#endif
|
||||
#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DDJGPP=2 -DMSDOS \
|
||||
-Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
/* We need to override link_command_spec in gcc.c so support -Tdjgpp.djl.
|
||||
This cannot be done in LINK_SPECS as that LINK_SPECS is processed
|
||||
before library search directories are known by the linker.
|
||||
This avoids problems when specs file is not available. An alternate way,
|
||||
suggested by Robert Hoehne, is to use SUBTARGET_EXTRA_SPECS instead.
|
||||
*/
|
||||
|
||||
#undef LINK_COMMAND_SPEC
|
||||
#define LINK_COMMAND_SPEC \
|
||||
"%{!fsyntax-only: \
|
||||
%{!c:%{!M:%{!MM:%{!E:%{!S:%(linker) %l %X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} \
|
||||
\t%{r} %{s} %{t} %{u*} %{x} %{z} %{Z}\
|
||||
\t%{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
|
||||
\t%{static:} %{L*} %D %o\
|
||||
\t%{!nostdlib:%{!nodefaultlibs:%G %L %G}}\
|
||||
\t%{!A:%{!nostdlib:%{!nostartfiles:%E}}}\
|
||||
\t-Tdjgpp.djl %{T*}}}}}}}\n\
|
||||
%{!c:%{!M:%{!MM:%{!E:%{!S:stubify %{v} %{o*:%*} %{!o*:a.out} }}}}}"
|
||||
|
||||
/* Always just link in 'libc.a'. */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "-lc"
|
||||
|
||||
/* Pick the right startup code depending on the -pg flag. */
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{pg:gcrt0.o%s}%{!pg:crt0.o%s}"
|
||||
|
||||
/* Make sure that gcc will not look for .h files in /usr/local/include
|
||||
unless user explicitly requests it. */
|
||||
#undef LOCAL_INCLUDE_DIR
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_ctor, in_dtor
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CTOR_SECTION_FUNCTION \
|
||||
DTOR_SECTION_FUNCTION
|
||||
|
||||
#define CTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
ctor_section () \
|
||||
{ \
|
||||
if (in_section != in_ctor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .ctor\n"); \
|
||||
in_section = in_ctor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTOR_SECTION_FUNCTION \
|
||||
void \
|
||||
dtor_section () \
|
||||
{ \
|
||||
if (in_section != in_dtor) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\t.section .dtor\n"); \
|
||||
in_section = in_dtor; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Allow (eg) __attribute__((section "locked")) to work */
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC)\
|
||||
do { \
|
||||
fprintf (FILE, "\t.section %s\n", NAME); \
|
||||
} while (0)
|
||||
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtor_section (); \
|
||||
fprintf (FILE, "%s\t", ASM_LONG); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Output at beginning of assembler file. */
|
||||
/* The .file command should always begin the output. */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { \
|
||||
output_file_directive (FILE, main_input_filename); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to output an assembler line
|
||||
that says to advance the location counter
|
||||
to a multiple of 2**LOG bytes. */
|
||||
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
if ((LOG) != 0) fprintf ((FILE), "\t.p2align %d\n", LOG)
|
||||
|
||||
/* djgpp has atexit (). */
|
||||
#undef HAVE_ATEXIT
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
/* djgpp automatically calls its own version of __main, so don't define one
|
||||
in libgcc, nor call one in main(). */
|
||||
#define HAS_INIT_SECTION
|
@ -3,6 +3,7 @@
|
||||
Contributed by Eric Youngdale.
|
||||
Modified for stabs-in-ELF by H.J. Lu.
|
||||
Adapted from GNU/Linux version by John Polstra.
|
||||
Continued development by David O'Brien <obrien@freebsd.org>
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -34,6 +35,23 @@ Boston, MA 02111-1307, USA. */
|
||||
libraries compiled with the native cc, so undef it. */
|
||||
#undef NO_DOLLAR_IN_LABEL
|
||||
|
||||
/* Use more efficient ``thunks'' to implement C++ vtables. */
|
||||
#undef DEFAULT_VTABLE_THUNKS
|
||||
#define DEFAULT_VTABLE_THUNKS 1
|
||||
|
||||
/* Override the default comment-starter of "/". */
|
||||
#undef ASM_COMMENT_START
|
||||
#define ASM_COMMENT_START "#"
|
||||
|
||||
#undef ASM_APP_ON
|
||||
#define ASM_APP_ON "#APP\n"
|
||||
|
||||
#undef ASM_APP_OFF
|
||||
#define ASM_APP_OFF "#NO_APP\n"
|
||||
|
||||
#undef SET_ASM_OP
|
||||
#define SET_ASM_OP ".set"
|
||||
|
||||
/* This is how to output an element of a case-vector that is relative.
|
||||
This is only used for PIC code. See comments by the `casesi' insn in
|
||||
i386.md for an explanation of the expression this outputs. */
|
||||
@ -45,6 +63,10 @@ Boston, MA 02111-1307, USA. */
|
||||
necessary when compiling PIC code. */
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
|
||||
|
||||
/* Use stabs instead of DWARF debug format. */
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
|
||||
/* Copy this from the svr4 specifications... */
|
||||
/* Define the register numbers to be used in Dwarf debugging information.
|
||||
The SVR4 reference port C compiler uses the following register numbers
|
||||
@ -113,23 +135,15 @@ Boston, MA 02111-1307, USA. */
|
||||
: ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \
|
||||
: (-1))
|
||||
|
||||
/* Output assembler code to FILE to increment profiler label # LABELNO
|
||||
for profiling a function entry. */
|
||||
/* Tell final.c that we don't need a label passed to mcount. */
|
||||
|
||||
#undef FUNCTION_PROFILER
|
||||
#define FUNCTION_PROFILER(FILE, LABELNO) \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
{ \
|
||||
fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \
|
||||
LPREFIX, (LABELNO)); \
|
||||
fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \
|
||||
} \
|
||||
fprintf (FILE, "\tcall *.mcount@GOT(%%ebx)\n"); \
|
||||
else \
|
||||
{ \
|
||||
fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \
|
||||
fprintf (FILE, "\tcall mcount\n"); \
|
||||
} \
|
||||
fprintf (FILE, "\tcall .mcount\n"); \
|
||||
}
|
||||
|
||||
#undef SIZE_TYPE
|
||||
@ -140,6 +154,9 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "int"
|
||||
|
||||
#undef WCHAR_UNSIGNED
|
||||
#define WCHAR_UNSIGNED 0
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE BITS_PER_WORD
|
||||
@ -150,21 +167,53 @@ Boston, MA 02111-1307, USA. */
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
|
||||
|
||||
#undef LIB_SPEC
|
||||
#if 1
|
||||
/* We no longer link with libc_p.a or libg.a by default. If you
|
||||
* want to profile or debug the C library, please add
|
||||
* -lc_p or -ggdb to LDFLAGS at the link time, respectively.
|
||||
*/
|
||||
#define LIB_SPEC \
|
||||
"%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \
|
||||
%{!ggdb:-lc} %{ggdb:-lg}}"
|
||||
#else
|
||||
#define LIB_SPEC \
|
||||
/* This defines which switch letters take arguments. On FreeBSD, most of
|
||||
the normal cases (defined in gcc.c) apply, and we also have -h* and
|
||||
-z* options (for the linker) (comming from svr4).
|
||||
We also have -R (alias --rpath), no -z, --soname (-h), --assert etc. */
|
||||
|
||||
#undef SWITCH_TAKES_ARG
|
||||
#define SWITCH_TAKES_ARG(CHAR) \
|
||||
(DEFAULT_SWITCH_TAKES_ARG (CHAR) \
|
||||
|| (CHAR) == 'h' \
|
||||
|| (CHAR) == 'z' \
|
||||
|| (CHAR) == 'R')
|
||||
|
||||
/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
|
||||
the magical crtbegin.o file (see crtstuff.c) which provides part
|
||||
of the support for getting C++ file-scope static object constructed
|
||||
before entering `main'. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: \
|
||||
%{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \
|
||||
%{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}"
|
||||
#endif
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
|
||||
%{!p:%{profile:gcrt1.o%s} \
|
||||
%{!profile:crt1.o%s}}}} \
|
||||
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
|
||||
|
||||
/* Provide a ENDFILE_SPEC appropriate for FreeBSD. Here we tack on
|
||||
the magical crtend.o file (see crtstuff.c) which provides part of
|
||||
the support for getting C++ file-scope static object constructed
|
||||
before entering `main', followed by a normal "finalizer" file,
|
||||
`crtn.o'. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
|
||||
|
||||
/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate
|
||||
libc, depending on whether we're doing profiling or need threads support.
|
||||
(simular to the default, except no -lg, and no -p. */
|
||||
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "%{!shared: \
|
||||
%{!pg:%{!pthread:%{!kthread:-lc} \
|
||||
%{kthread:-lpthread -lc}} \
|
||||
%{pthread:-lc_r}} \
|
||||
%{pg:%{!pthread:%{!kthread:-lc_p} \
|
||||
%{kthread:-lpthread_p -lc_p}} \
|
||||
%{pthread:-lc_r_p}}}"
|
||||
|
||||
/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support
|
||||
for the special GCC options -static and -shared, which allow us to
|
||||
@ -181,15 +230,17 @@ Boston, MA 02111-1307, USA. */
|
||||
done. */
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
|
||||
%{!shared: \
|
||||
%{!ibcs: \
|
||||
#define LINK_SPEC "-m elf_i386 \
|
||||
%{Wl,*:%*} \
|
||||
%{v:-V} \
|
||||
%{assert*} %{R*} %{rpath*} %{defsym*} \
|
||||
%{shared:-Bshareable %{h*} %{soname*}} \
|
||||
%{!shared: \
|
||||
%{!static: \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \
|
||||
%{static:-static}}}"
|
||||
|
||||
/* Get perform_* macros to build libgcc.a. */
|
||||
%{static:-Bstatic}} \
|
||||
%{symbolic:-Bsymbolic}"
|
||||
|
||||
/* A C statement to output to the stdio stream FILE an assembler
|
||||
command to advance the location counter to a multiple of 1<<LOG
|
||||
@ -199,7 +250,8 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
|
||||
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
if ((LOG)!=0) \
|
||||
if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
|
||||
if ((LOG) != 0) {\
|
||||
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
|
||||
}
|
||||
#endif
|
||||
|
@ -94,9 +94,10 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
|
||||
# define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
if ((LOG)!=0) \
|
||||
if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
|
||||
if ((LOG) != 0) {\
|
||||
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* A C statement or statements which output an assembler instruction
|
||||
|
@ -3,13 +3,24 @@
|
||||
/* This does it mostly for us. */
|
||||
#include <i386/linux.h>
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Di386 -Acpu(i386) -Amachine(i386) \
|
||||
-Dunix -Asystem(unix) -DMACH -Asystem(mach) -D__GNU__ -Asystem(gnu)"
|
||||
/* Get machine-independent configuration parameters for the GNU system. */
|
||||
#include <gnu.h>
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (i386 GNU)");
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-D__ELF__ -D__i386__ -DMACH -Asystem(mach) \
|
||||
-Dunix -Asystem(unix) -Asystem(posix) -D__GNU__ -Asystem(gnu)"
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "%(cpp_cpu) \
|
||||
%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} \
|
||||
%{posix:-D_POSIX_SOURCE} %{bsd:-D_BSD_SOURCE}"
|
||||
|
||||
#undef CC1_SPEC
|
||||
#define CC1_SPEC "%(cc1_cpu)"
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
|
||||
%{!shared: \
|
||||
@ -18,6 +29,10 @@
|
||||
%{!dynamic-linker:-dynamic-linker /lib/ld.so}} \
|
||||
%{static:-static}}"
|
||||
|
||||
|
||||
/* Get machine-independent configuration parameters for the GNU system. */
|
||||
#include <gnu.h>
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: \
|
||||
%{!static: \
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}} \
|
||||
%{static:crt0.o%s}} \
|
||||
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
|
||||
|
@ -22,14 +22,20 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
|
||||
#include "i386/gas.h"
|
||||
#include "dbxcoff.h"
|
||||
|
||||
/* Specify predefined symbols in preprocessor. */
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Di386"
|
||||
|
||||
/* We want to be able to get DBX debugging information via -gstabs. */
|
||||
|
||||
#undef DBX_DEBUGGING_INFO
|
||||
#define SDB_DEBUGGING_INFO
|
||||
#define DBX_DEBUGGING_INFO
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE SDB_DEBUG
|
||||
|
||||
/* Support the ctors and dtors sections for g++. */
|
||||
|
||||
|
575
contrib/gcc/config/i386/i386-interix.h
Normal file
575
contrib/gcc/config/i386/i386-interix.h
Normal file
@ -0,0 +1,575 @@
|
||||
/* Target definitions for GNU compiler for Intel 80386 running Interix
|
||||
Parts Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
|
||||
Parts:
|
||||
by Douglas B. Rupp (drupp@cs.washington.edu).
|
||||
by Ron Guilmette (rfg@netcom.com).
|
||||
by Donn Terry (donn@softway.com).
|
||||
by Mumit Khan (khan@xraylith.wisc.edu).
|
||||
|
||||
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. */
|
||||
|
||||
#define YES_UNDERSCORES
|
||||
|
||||
/* YES_UNDERSCORES must preceed gas.h */
|
||||
#include <i386/gas.h>
|
||||
/* The rest must follow. */
|
||||
|
||||
#define DBX_DEBUGGING_INFO
|
||||
#define SDB_DEBUGGING_INFO
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
|
||||
#define HANDLE_SYSV_PRAGMA
|
||||
#undef HANDLE_PRAGMA_WEAK /* until the link format can handle it */
|
||||
|
||||
/* By default, target has a 80387, uses IEEE compatible arithmetic,
|
||||
and returns float values in the 387 and needs stack probes
|
||||
We also align doubles to 64-bits for MSVC default compatability */
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT \
|
||||
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE | \
|
||||
MASK_ALIGN_DOUBLE)
|
||||
|
||||
#undef TARGET_CPU_DEFAULT
|
||||
#define TARGET_CPU_DEFAULT 2 /* 486 */
|
||||
|
||||
#define WCHAR_UNSIGNED 1
|
||||
#define WCHAR_TYPE_SIZE 16
|
||||
#define WCHAR_TYPE "short unsigned int"
|
||||
|
||||
/* WinNT (and thus Interix) use unsigned int */
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
#define ASM_LOAD_ADDR(loc, reg) " leal " #loc "," #reg "\n"
|
||||
|
||||
/* For the sake of libgcc2.c, indicate target supports atexit. */
|
||||
#define HAVE_ATEXIT
|
||||
|
||||
/* cpp handles __STDC__ */
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES " \
|
||||
-D__INTERIX \
|
||||
-D__OPENNT \
|
||||
-D_M_IX86=300 -D_X86_=1 \
|
||||
-D__stdcall=__attribute__((__stdcall__)) \
|
||||
-D__cdecl=__attribute__((__cdecl__)) \
|
||||
-Asystem(unix) -Asystem(interix) -Asystem(interix) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
#undef CPP_SPEC
|
||||
/* Write out the correct language type definition for the header files.
|
||||
Unless we have assembler language, write out the symbols for C.
|
||||
cpp_cpu is an Intel specific variant. See i386.h
|
||||
mieee is an Alpha specific variant. Cross polination a bad idea.
|
||||
*/
|
||||
#define CPP_SPEC "\
|
||||
%{!.S: -D__LANGUAGE_C__ -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}} \
|
||||
%{.S: -D__LANGUAGE_ASSEMBLY__ -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \
|
||||
%{.cc: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
|
||||
%{.cxx: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
|
||||
%{.C: -D__LANGUAGE_C_PLUS_PLUS__ -D__LANGUAGE_C_PLUS_PLUS -D__cplusplus} \
|
||||
%{.m: -D__LANGUAGE_OBJECTIVE_C__ -D__LANGUAGE_OBJECTIVE_C} \
|
||||
-remap \
|
||||
%(cpp_cpu) \
|
||||
%{posix:-D_POSIX_SOURCE} \
|
||||
-idirafter %$INTERIX_ROOT/usr/include"
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (i386 Interix)");
|
||||
|
||||
/* The global __fltused is necessary to cause the printf/scanf routines
|
||||
for outputting/inputting floating point numbers to be loaded. Since this
|
||||
is kind of hard to detect, we just do it all the time. */
|
||||
|
||||
#ifdef ASM_FILE_START
|
||||
#undef ASM_FILE_START
|
||||
#endif
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { fprintf (FILE, "\t.file\t"); \
|
||||
output_quoted_string (FILE, dump_base_name); \
|
||||
fprintf (FILE, "\n"); \
|
||||
fprintf (FILE, ".global\t__fltused\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A table of bytes codes used by the ASM_OUTPUT_ASCII and
|
||||
ASM_OUTPUT_LIMITED_STRING macros. Each byte in the table
|
||||
corresponds to a particular byte value [0..255]. For any
|
||||
given byte value, if the value in the corresponding table
|
||||
position is zero, the given character can be output directly.
|
||||
If the table value is 1, the byte must be output as a \ooo
|
||||
octal escape. If the tables value is anything else, then the
|
||||
byte value should be output as a \ followed by the value
|
||||
in the table. Note that we can use standard UN*X escape
|
||||
sequences for many control characters, but we don't use
|
||||
\a to represent BEL because some svr4 assemblers (e.g. on
|
||||
the i386) don't know about that. Also, we don't use \v
|
||||
since some versions of gas, such as 2.2 did not accept it. */
|
||||
|
||||
#define ESCAPES \
|
||||
"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\
|
||||
\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\
|
||||
\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1"
|
||||
|
||||
/* Some svr4 assemblers have a limit on the number of characters which
|
||||
can appear in the operand of a .string directive. If your assembler
|
||||
has such a limitation, you should define STRING_LIMIT to reflect that
|
||||
limit. Note that at least some svr4 assemblers have a limit on the
|
||||
actual number of bytes in the double-quoted string, and that they
|
||||
count each character in an escape sequence as one byte. Thus, an
|
||||
escape sequence like \377 would count as four bytes.
|
||||
|
||||
If your target assembler doesn't support the .string directive, you
|
||||
should define this to zero.
|
||||
*/
|
||||
|
||||
#define STRING_LIMIT ((unsigned) 256)
|
||||
|
||||
#define STRING_ASM_OP ".string"
|
||||
|
||||
/* The routine used to output NUL terminated strings. We use a special
|
||||
version of this for most svr4 targets because doing so makes the
|
||||
generated assembly code more compact (and thus faster to assemble)
|
||||
as well as more readable, especially for targets like the i386
|
||||
(where the only alternative is to output character sequences as
|
||||
comma separated lists of numbers). */
|
||||
|
||||
#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
|
||||
do \
|
||||
{ \
|
||||
register unsigned char *_limited_str = (unsigned char *) (STR); \
|
||||
register unsigned ch; \
|
||||
fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \
|
||||
for (; (ch = *_limited_str); _limited_str++) \
|
||||
{ \
|
||||
register int escape = ESCAPES[ch]; \
|
||||
switch (escape) \
|
||||
{ \
|
||||
case 0: \
|
||||
putc (ch, (FILE)); \
|
||||
break; \
|
||||
case 1: \
|
||||
fprintf ((FILE), "\\%03o", ch); \
|
||||
break; \
|
||||
default: \
|
||||
putc ('\\', (FILE)); \
|
||||
putc (escape, (FILE)); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* The routine used to output sequences of byte values. We use a special
|
||||
version of this for most svr4 targets because doing so makes the
|
||||
generated assembly code more compact (and thus faster to assemble)
|
||||
as well as more readable. Note that if we find subparts of the
|
||||
character sequence which end with NUL (and which are shorter than
|
||||
STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
|
||||
|
||||
#undef ASM_OUTPUT_ASCII
|
||||
#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
|
||||
do \
|
||||
{ \
|
||||
register unsigned char *_ascii_bytes = (unsigned char *) (STR); \
|
||||
register unsigned char *limit = _ascii_bytes + (LENGTH); \
|
||||
register unsigned bytes_in_chunk = 0; \
|
||||
for (; _ascii_bytes < limit; _ascii_bytes++) \
|
||||
{ \
|
||||
register unsigned char *p; \
|
||||
if (bytes_in_chunk >= 64) \
|
||||
{ \
|
||||
fputc ('\n', (FILE)); \
|
||||
bytes_in_chunk = 0; \
|
||||
} \
|
||||
for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
|
||||
continue; \
|
||||
if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \
|
||||
{ \
|
||||
if (bytes_in_chunk > 0) \
|
||||
{ \
|
||||
fputc ('\n', (FILE)); \
|
||||
bytes_in_chunk = 0; \
|
||||
} \
|
||||
ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \
|
||||
_ascii_bytes = p; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (bytes_in_chunk == 0) \
|
||||
fprintf ((FILE), "\t.byte\t"); \
|
||||
else \
|
||||
fputc (',', (FILE)); \
|
||||
fprintf ((FILE), "0x%02x", *_ascii_bytes); \
|
||||
bytes_in_chunk += 5; \
|
||||
} \
|
||||
} \
|
||||
if (bytes_in_chunk > 0) \
|
||||
fprintf ((FILE), "\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* This is how to output an element of a case-vector that is relative.
|
||||
This is only used for PIC code. See comments by the `casesi' insn in
|
||||
i386.md for an explanation of the expression this outputs.
|
||||
PE format differs on what PC-relative offsets look like (see
|
||||
coff_i386_rtype_to_howto), and we need to compensate (by one word) here. */
|
||||
|
||||
#undef ASM_OUTPUT_ADDR_DIFF_ELT
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
|
||||
fprintf (FILE, "\t.long __GLOBAL_OFFSET_TABLE_+[.-%s%d+4]\n", LPREFIX, VALUE)
|
||||
|
||||
/* Indicate that jump tables go in the text section. This is
|
||||
necessary when compiling PIC code. */
|
||||
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
|
||||
/* Emit code to check the stack when allocating more that 4000
|
||||
bytes in one go. */
|
||||
|
||||
#define CHECK_STACK_LIMIT 0x1000
|
||||
|
||||
/* the following are OSF linker (not gld) specific... we don't want them */
|
||||
#undef HAS_INIT_SECTION
|
||||
#undef LD_INIT_SWITCH
|
||||
#undef LD_FINI_SWITCH
|
||||
|
||||
|
||||
/* The following are needed for C++, but also needed for profiling */
|
||||
|
||||
/* Support const sections and the ctors and dtors sections for g++.
|
||||
Note that there appears to be two different ways to support const
|
||||
sections at the moment. You can either #define the symbol
|
||||
READONLY_DATA_SECTION (giving it some code which switches to the
|
||||
readonly data section) or else you can #define the symbols
|
||||
EXTRA_SECTIONS, EXTRA_SECTION_FUNCTIONS, SELECT_SECTION, and
|
||||
SELECT_RTX_SECTION. We do both here just to be on the safe side. */
|
||||
|
||||
#define USE_CONST_SECTION 1
|
||||
|
||||
#define CONST_SECTION_ASM_OP ".section\t.rdata,\"r\""
|
||||
|
||||
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
|
||||
|
||||
Note that we want to give these sections the SHF_WRITE attribute
|
||||
because these sections will actually contain data (i.e. tables of
|
||||
addresses of functions in the current root executable or shared library
|
||||
file) and, in the case of a shared library, the relocatable addresses
|
||||
will have to be properly resolved/relocated (and then written into) by
|
||||
the dynamic linker when it actually attaches the given shared library
|
||||
to the executing process. (Note that on SVR4, you may wish to use the
|
||||
`-z text' option to the ELF linker, when building a shared library, as
|
||||
an additional check that you are doing everything right. But if you do
|
||||
use the `-z text' option when building a shared library, you will get
|
||||
errors unless the .ctors and .dtors sections are marked as writable
|
||||
via the SHF_WRITE attribute.) */
|
||||
|
||||
#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"x\""
|
||||
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"x\""
|
||||
|
||||
/* A default list of other sections which we might be "in" at any given
|
||||
time. For targets that use additional sections (e.g. .tdesc) you
|
||||
should override this definition in the target-specific file which
|
||||
includes this file. */
|
||||
|
||||
#undef EXTRA_SECTIONS
|
||||
#define EXTRA_SECTIONS in_const, in_ctors, in_dtors
|
||||
|
||||
/* A default list of extra section function definitions. For targets
|
||||
that use additional sections (e.g. .tdesc) you should override this
|
||||
definition in the target-specific file which includes this file. */
|
||||
|
||||
#undef EXTRA_SECTION_FUNCTIONS
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
CONST_SECTION_FUNCTION \
|
||||
CTORS_SECTION_FUNCTION \
|
||||
DTORS_SECTION_FUNCTION
|
||||
|
||||
#undef READONLY_DATA_SECTION
|
||||
#define READONLY_DATA_SECTION() const_section ()
|
||||
|
||||
extern void text_section ();
|
||||
|
||||
#define CONST_SECTION_FUNCTION \
|
||||
void \
|
||||
const_section () \
|
||||
{ \
|
||||
if (!USE_CONST_SECTION) \
|
||||
text_section(); \
|
||||
else if (in_section != in_const) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \
|
||||
in_section = in_const; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
ctors_section () \
|
||||
{ \
|
||||
if (in_section != in_ctors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \
|
||||
in_section = in_ctors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DTORS_SECTION_FUNCTION \
|
||||
void \
|
||||
dtors_section () \
|
||||
{ \
|
||||
if (in_section != in_dtors) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \
|
||||
in_section = in_dtors; \
|
||||
} \
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Currently gas chokes on this; that's not too hard to fix, but there's
|
||||
not a lot of impeteus to do it, either. If it is done, gas will have
|
||||
to handle long section name escapes (which are defined in the COFF/PE
|
||||
document as /nnn where nnn is a string table index). The benefit:
|
||||
section attributes and -ffunction-sections, neither of which seem to
|
||||
be critical. */
|
||||
/* gas may have been fixed? bfd was. */
|
||||
|
||||
/* Switch into a generic section.
|
||||
This is currently only used to support section attributes.
|
||||
|
||||
We make the section read-only and executable for a function decl,
|
||||
read-only for a const data decl, and writable for a non-const data decl. */
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
|
||||
fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \
|
||||
(DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \
|
||||
(DECL) && TREE_READONLY (DECL) ? "a" : "aw")
|
||||
#endif
|
||||
|
||||
#define INT_ASM_OP ".long"
|
||||
|
||||
/* The MS compilers take alignment as a number of bytes, so we do as well */
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
|
||||
if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global constructors. */
|
||||
#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
ctors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement (sans semicolon) to output an element in the table of
|
||||
global destructors. */
|
||||
#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \
|
||||
do { \
|
||||
dtors_section (); \
|
||||
fprintf (FILE, "\t%s\t ", INT_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* The linker will take care of this, and having them causes problems with
|
||||
ld -r (specifically -rU). */
|
||||
#define CTOR_LISTS_DEFINED_EXTERNALLY 1
|
||||
|
||||
#define SET_ASM_OP ".set"
|
||||
/* Output a definition (implements alias) */
|
||||
#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
|
||||
do \
|
||||
{ \
|
||||
fprintf ((FILE), "\t%s\t", SET_ASM_OP); \
|
||||
assemble_name (FILE, LABEL1); \
|
||||
fprintf (FILE, ","); \
|
||||
assemble_name (FILE, LABEL2); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define HOST_PTR_PRINTF "%p"
|
||||
#define HOST_PTR_AS_INT unsigned long
|
||||
|
||||
#define PCC_BITFIELD_TYPE_MATTERS 1
|
||||
#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec)
|
||||
#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec)
|
||||
|
||||
/* The following two flags are usually "off" for i386, because some non-gnu
|
||||
tools (for the i386) don't handle them. However, we don't have that
|
||||
problem, so.... */
|
||||
|
||||
/* Forward references to tags are allowed. */
|
||||
#define SDB_ALLOW_FORWARD_REFERENCES
|
||||
|
||||
/* Unknown tags are also allowed. */
|
||||
#define SDB_ALLOW_UNKNOWN_REFERENCES
|
||||
|
||||
/* The integer half of this list needs to be constant. However, there's
|
||||
a lot of disagreement about what the floating point adjustments should
|
||||
be. We pick one that works with gdb. (The underlying problem is
|
||||
what to do about the segment registers. Since we have access to them
|
||||
from /proc, we'll allow them to be accessed in gdb, even tho the
|
||||
gcc compiler can't generate them. (There's some evidence that
|
||||
MSVC does, but possibly only for certain special "canned" sequences.) */
|
||||
|
||||
#undef DBX_REGISTER_NUMBER
|
||||
#define DBX_REGISTER_NUMBER(n) \
|
||||
((n) == 0 ? 0 \
|
||||
: (n) == 1 ? 2 \
|
||||
: (n) == 2 ? 1 \
|
||||
: (n) == 3 ? 3 \
|
||||
: (n) == 4 ? 6 \
|
||||
: (n) == 5 ? 7 \
|
||||
: (n) == 6 ? 5 \
|
||||
: (n) == 7 ? 4 \
|
||||
: ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+8 \
|
||||
: (-1))
|
||||
|
||||
/* Define this macro if references to a symbol must be treated
|
||||
differently depending on something about the variable or
|
||||
function named by the symbol (such as what section it is in).
|
||||
|
||||
Apply stddef, handle (as yet unimplemented) pic.
|
||||
|
||||
stddef renaming does NOT apply to Alpha. */
|
||||
|
||||
char *gen_stdcall_suffix ();
|
||||
|
||||
#undef ENCODE_SECTION_INFO
|
||||
#define ENCODE_SECTION_INFO(DECL) \
|
||||
do \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
{ \
|
||||
rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
|
||||
? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \
|
||||
SYMBOL_REF_FLAG (XEXP (rtl, 0)) \
|
||||
= (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \
|
||||
|| ! TREE_PUBLIC (DECL)); \
|
||||
} \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
if (lookup_attribute ("stdcall", \
|
||||
TYPE_ATTRIBUTES (TREE_TYPE (DECL)))) \
|
||||
XEXP (DECL_RTL (DECL), 0) = \
|
||||
gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (DECL)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* This macro gets just the user-specified name
|
||||
out of the string in a SYMBOL_REF. Discard
|
||||
trailing @[NUM] encoded by ENCODE_SECTION_INFO. */
|
||||
#undef STRIP_NAME_ENCODING
|
||||
#define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME) \
|
||||
do { \
|
||||
char *_p; \
|
||||
char *_name = SYMBOL_NAME; \
|
||||
for (_p = _name; *_p && *_p != '@'; ++_p) \
|
||||
; \
|
||||
if (*_p == '@') \
|
||||
{ \
|
||||
int _len = _p - _name; \
|
||||
(VAR) = (char *) alloca (_len + 1); \
|
||||
strncpy ((VAR), _name, _len); \
|
||||
(VAR)[_len] = '\0'; \
|
||||
} \
|
||||
else \
|
||||
(VAR) = _name; \
|
||||
} while (0)
|
||||
|
||||
#if 0
|
||||
/* Turn this back on when the linker is updated to handle grouped
|
||||
.data$ sections correctly. See corresponding note in i386/interix.c.
|
||||
MK. */
|
||||
|
||||
/* Define this macro if in some cases global symbols from one translation
|
||||
unit may not be bound to undefined symbols in another translation unit
|
||||
without user intervention. For instance, under Microsoft Windows
|
||||
symbols must be explicitly imported from shared libraries (DLLs). */
|
||||
#define MULTIPLE_SYMBOL_SPACES
|
||||
|
||||
#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL)
|
||||
extern void i386_pe_unique_section ();
|
||||
#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC)
|
||||
|
||||
#define SUPPORTS_ONE_ONLY 1
|
||||
|
||||
/* A C statement to output something to the assembler file to switch to section
|
||||
NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or
|
||||
NULL_TREE. Some target formats do not support arbitrary sections. Do not
|
||||
define this macro in such cases. */
|
||||
#undef ASM_OUTPUT_SECTION_NAME
|
||||
#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
|
||||
do { \
|
||||
static struct section_info \
|
||||
{ \
|
||||
struct section_info *next; \
|
||||
char *name; \
|
||||
enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
|
||||
} *sections; \
|
||||
struct section_info *s; \
|
||||
char *mode; \
|
||||
enum sect_enum type; \
|
||||
\
|
||||
for (s = sections; s; s = s->next) \
|
||||
if (!strcmp (NAME, s->name)) \
|
||||
break; \
|
||||
\
|
||||
if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
type = SECT_EXEC, mode = "x"; \
|
||||
else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
type = SECT_RO, mode = "r"; \
|
||||
else \
|
||||
type = SECT_RW, mode = "w"; \
|
||||
\
|
||||
if (s == 0) \
|
||||
{ \
|
||||
s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
|
||||
s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
|
||||
strcpy (s->name, NAME); \
|
||||
s->type = type; \
|
||||
s->next = sections; \
|
||||
sections = s; \
|
||||
fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
|
||||
/* Functions may have been compiled at various levels of \
|
||||
optimization so we can't use `same_size' here. Instead, \
|
||||
have the linker pick one. */ \
|
||||
if ((DECL) && DECL_ONE_ONLY (DECL)) \
|
||||
fprintf (STREAM, "\t.linkonce %s\n", \
|
||||
TREE_CODE (DECL) == FUNCTION_DECL \
|
||||
? "discard" : "same_size"); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fprintf (STREAM, ".section\t%s,\"%s\"\n", NAME, mode); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
/* DWARF2 Unwinding doesn't work with exception handling yet. */
|
||||
#define DWARF2_UNWIND_INFO 0
|
||||
|
||||
/* Don't assume anything about the header files. */
|
||||
#define NO_IMPLICIT_EXTERN_C
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -155,62 +155,67 @@ extern int target_flags;
|
||||
#define TARGET_486 (ix86_cpu == PROCESSOR_I486)
|
||||
#define TARGET_PENTIUM (ix86_cpu == PROCESSOR_PENTIUM)
|
||||
#define TARGET_PENTIUMPRO (ix86_cpu == PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_USE_LEAVE (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_PUSH_MEMORY (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386 \
|
||||
&& ix86_cpu != PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_DOUBLE_WITH_ADD (ix86_cpu != PROCESSOR_I386)
|
||||
#define TARGET_USE_BIT_TEST (ix86_cpu == PROCESSOR_I386)
|
||||
#define TARGET_UNROLL_STRLEN (ix86_cpu != PROCESSOR_I386)
|
||||
#define TARGET_USE_Q_REG (ix86_cpu == PROCESSOR_PENTIUM \
|
||||
|| ix86_cpu == PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_USE_ANY_REG (ix86_cpu == PROCESSOR_I486)
|
||||
#define TARGET_CMOVE (ix86_arch == PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_DEEP_BRANCH_PREDICTION (ix86_cpu == PROCESSOR_PENTIUMPRO)
|
||||
#define TARGET_K6 (ix86_cpu == PROCESSOR_K6)
|
||||
|
||||
#define CPUMASK (1 << ix86_cpu)
|
||||
extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
|
||||
extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
|
||||
extern const int x86_unroll_strlen, x86_use_q_reg, x86_use_any_reg;
|
||||
extern const int x86_double_with_add;
|
||||
|
||||
#define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
|
||||
#define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
|
||||
#define TARGET_ZERO_EXTEND_WITH_AND (x86_zero_extend_with_and & CPUMASK)
|
||||
#define TARGET_USE_BIT_TEST (x86_use_bit_test & CPUMASK)
|
||||
#define TARGET_UNROLL_STRLEN (x86_unroll_strlen & CPUMASK)
|
||||
#define TARGET_USE_Q_REG (x86_use_q_reg & CPUMASK)
|
||||
#define TARGET_USE_ANY_REG (x86_use_any_reg & CPUMASK)
|
||||
#define TARGET_CMOVE (x86_cmove & (1 << ix86_arch))
|
||||
#define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
|
||||
#define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
|
||||
|
||||
#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
|
||||
|
||||
#define TARGET_SWITCHES \
|
||||
{ { "80387", MASK_80387 }, \
|
||||
{ "no-80387", -MASK_80387 }, \
|
||||
{ "hard-float", MASK_80387 }, \
|
||||
{ "soft-float", -MASK_80387 }, \
|
||||
{ "no-soft-float", MASK_80387 }, \
|
||||
{ "386", 0 }, \
|
||||
{ "no-386", 0 }, \
|
||||
{ "486", 0 }, \
|
||||
{ "no-486", 0 }, \
|
||||
{ "pentium", 0 }, \
|
||||
{ "pentiumpro", 0 }, \
|
||||
{ "rtd", MASK_RTD }, \
|
||||
{ "no-rtd", -MASK_RTD }, \
|
||||
{ "align-double", MASK_ALIGN_DOUBLE }, \
|
||||
{ "no-align-double", -MASK_ALIGN_DOUBLE }, \
|
||||
{ "svr3-shlib", MASK_SVR3_SHLIB }, \
|
||||
{ "no-svr3-shlib", -MASK_SVR3_SHLIB }, \
|
||||
{ "ieee-fp", MASK_IEEE_FP }, \
|
||||
{ "no-ieee-fp", -MASK_IEEE_FP }, \
|
||||
{ "fp-ret-in-387", MASK_FLOAT_RETURNS }, \
|
||||
{ "no-fp-ret-in-387", -MASK_FLOAT_RETURNS }, \
|
||||
{ "no-fancy-math-387", MASK_NO_FANCY_MATH_387 }, \
|
||||
{ "fancy-math-387", -MASK_NO_FANCY_MATH_387 }, \
|
||||
{ "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER }, \
|
||||
{ "no-omit-leaf-frame-pointer",-MASK_OMIT_LEAF_FRAME_POINTER }, \
|
||||
{ "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \
|
||||
{ "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \
|
||||
{ "schedule-prologue", MASK_SCHEDULE_PROLOGUE }, \
|
||||
{ "no-schedule-prologue", -MASK_SCHEDULE_PROLOGUE }, \
|
||||
{ "debug-addr", MASK_DEBUG_ADDR }, \
|
||||
{ "no-debug-addr", -MASK_DEBUG_ADDR }, \
|
||||
{ "move", -MASK_NO_MOVE }, \
|
||||
{ "no-move", MASK_NO_MOVE }, \
|
||||
{ "debug-arg", MASK_DEBUG_ARG }, \
|
||||
{ "no-debug-arg", -MASK_DEBUG_ARG }, \
|
||||
{ "stack-arg-probe", MASK_STACK_PROBE }, \
|
||||
{ "no-stack-arg-probe", -MASK_STACK_PROBE }, \
|
||||
{ "windows", 0 }, \
|
||||
{ "dll", 0 }, \
|
||||
{ { "80387", MASK_80387, "Use hardware fp" }, \
|
||||
{ "no-80387", -MASK_80387, "Do not use hardware fp" },\
|
||||
{ "hard-float", MASK_80387, "Use hardware fp" }, \
|
||||
{ "soft-float", -MASK_80387, "Do not use hardware fp" },\
|
||||
{ "no-soft-float", MASK_80387, "Use hardware fp" }, \
|
||||
{ "386", 0, "Same as -mcpu=i386" }, \
|
||||
{ "486", 0, "Same as -mcpu=i486" }, \
|
||||
{ "pentium", 0, "Same as -mcpu=pentium" }, \
|
||||
{ "pentiumpro", 0, "Same as -mcpu=pentiumpro" }, \
|
||||
{ "rtd", MASK_RTD, "Alternate calling convention" },\
|
||||
{ "no-rtd", -MASK_RTD, "Use normal calling convention" },\
|
||||
{ "align-double", MASK_ALIGN_DOUBLE, "Align some doubles on dword boundary" },\
|
||||
{ "no-align-double", -MASK_ALIGN_DOUBLE, "Align doubles on word boundary" }, \
|
||||
{ "svr3-shlib", MASK_SVR3_SHLIB, "Uninitialized locals in .bss" }, \
|
||||
{ "no-svr3-shlib", -MASK_SVR3_SHLIB, "Uninitialized locals in .data" }, \
|
||||
{ "ieee-fp", MASK_IEEE_FP, "Use IEEE math for fp comparisons" }, \
|
||||
{ "no-ieee-fp", -MASK_IEEE_FP, "Do not use IEEE math for fp comparisons" }, \
|
||||
{ "fp-ret-in-387", MASK_FLOAT_RETURNS, "Return values of functions in FPU registers" }, \
|
||||
{ "no-fp-ret-in-387", -MASK_FLOAT_RETURNS , "Do not return values of functions in FPU registers"}, \
|
||||
{ "no-fancy-math-387", MASK_NO_FANCY_MATH_387, "Do not generate sin, cos, sqrt for 387" }, \
|
||||
{ "fancy-math-387", -MASK_NO_FANCY_MATH_387, "Generate sin, cos, sqrt for FPU"}, \
|
||||
{ "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER, "Omit the frame pointer in leaf functions" }, \
|
||||
{ "no-omit-leaf-frame-pointer",-MASK_OMIT_LEAF_FRAME_POINTER, "" }, \
|
||||
{ "no-wide-multiply", MASK_NO_WIDE_MULTIPLY, "multiplies of 32 bits constrained to 32 bits" }, \
|
||||
{ "wide-multiply", -MASK_NO_WIDE_MULTIPLY, "multiplies of 32 bits are 64 bits" }, \
|
||||
{ "schedule-prologue", MASK_SCHEDULE_PROLOGUE, "Schedule function prologues" }, \
|
||||
{ "no-schedule-prologue", -MASK_SCHEDULE_PROLOGUE, "" }, \
|
||||
{ "debug-addr", MASK_DEBUG_ADDR, 0 /* intentionally undoc */ }, \
|
||||
{ "no-debug-addr", -MASK_DEBUG_ADDR, 0 /* intentionally undoc */ }, \
|
||||
{ "move", -MASK_NO_MOVE, "Generate mem-mem moves" }, \
|
||||
{ "no-move", MASK_NO_MOVE, "Don't generate mem-mem moves" }, \
|
||||
{ "debug-arg", MASK_DEBUG_ARG, 0 /* intentionally undoc */ }, \
|
||||
{ "no-debug-arg", -MASK_DEBUG_ARG, 0 /* intentionally undoc */ }, \
|
||||
{ "stack-arg-probe", MASK_STACK_PROBE, "Enable stack probing" }, \
|
||||
{ "no-stack-arg-probe", -MASK_STACK_PROBE, "" }, \
|
||||
{ "windows", 0, 0 /* intentionally undoc */ }, \
|
||||
{ "dll", 0, 0 /* intentionally undoc */ }, \
|
||||
SUBTARGET_SWITCHES \
|
||||
{ "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT}}
|
||||
{ "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT, 0 }}
|
||||
|
||||
/* Which processor to schedule for. The cpu attribute defines a list that
|
||||
mirrors this list, so changes to i386.md must be made at the same time. */
|
||||
@ -219,7 +224,8 @@ enum processor_type
|
||||
{PROCESSOR_I386, /* 80386 */
|
||||
PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */
|
||||
PROCESSOR_PENTIUM,
|
||||
PROCESSOR_PENTIUMPRO};
|
||||
PROCESSOR_PENTIUMPRO,
|
||||
PROCESSOR_K6};
|
||||
|
||||
#define PROCESSOR_I386_STRING "i386"
|
||||
#define PROCESSOR_I486_STRING "i486"
|
||||
@ -227,28 +233,20 @@ enum processor_type
|
||||
#define PROCESSOR_PENTIUM_STRING "pentium"
|
||||
#define PROCESSOR_I686_STRING "i686"
|
||||
#define PROCESSOR_PENTIUMPRO_STRING "pentiumpro"
|
||||
#define PROCESSOR_K6_STRING "k6"
|
||||
|
||||
extern enum processor_type ix86_cpu;
|
||||
|
||||
extern int ix86_arch;
|
||||
|
||||
/* Define the default processor. This is overridden by other tm.h files. */
|
||||
#define PROCESSOR_DEFAULT \
|
||||
((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
|
||||
? PROCESSOR_I486 \
|
||||
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
|
||||
? PROCESSOR_PENTIUM \
|
||||
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
|
||||
? PROCESSOR_PENTIUMPRO \
|
||||
: PROCESSOR_I386
|
||||
#define PROCESSOR_DEFAULT (enum processor_type) TARGET_CPU_DEFAULT
|
||||
#define PROCESSOR_DEFAULT_STRING \
|
||||
((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \
|
||||
? PROCESSOR_I486_STRING \
|
||||
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \
|
||||
? PROCESSOR_PENTIUM_STRING \
|
||||
: ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \
|
||||
? PROCESSOR_PENTIUMPRO_STRING \
|
||||
: PROCESSOR_I386_STRING
|
||||
(PROCESSOR_DEFAULT == PROCESSOR_I486 ? PROCESSOR_I486_STRING \
|
||||
: PROCESSOR_DEFAULT == PROCESSOR_PENTIUM ? PROCESSOR_PENTIUM_STRING \
|
||||
: PROCESSOR_DEFAULT == PROCESSOR_PENTIUMPRO ? PROCESSOR_PENTIUMPRO_STRING \
|
||||
: PROCESSOR_DEFAULT == PROCESSOR_K6 ? PROCESSOR_K6_STRING \
|
||||
: PROCESSOR_I386_STRING)
|
||||
|
||||
/* This macro is similar to `TARGET_SWITCHES' but defines names of
|
||||
command options that have values. Its definition is an
|
||||
@ -260,14 +258,15 @@ extern int ix86_arch;
|
||||
option if the fixed part matches. The actual option name is made
|
||||
by appending `-m' to the specified name. */
|
||||
#define TARGET_OPTIONS \
|
||||
{ { "cpu=", &ix86_cpu_string}, \
|
||||
{ "arch=", &ix86_arch_string}, \
|
||||
{ "reg-alloc=", &i386_reg_alloc_order }, \
|
||||
{ "regparm=", &i386_regparm_string }, \
|
||||
{ "align-loops=", &i386_align_loops_string }, \
|
||||
{ "align-jumps=", &i386_align_jumps_string }, \
|
||||
{ "align-functions=", &i386_align_funcs_string }, \
|
||||
{ "branch-cost=", &i386_branch_cost_string }, \
|
||||
{ { "cpu=", &ix86_cpu_string, "Schedule code for given CPU"}, \
|
||||
{ "arch=", &ix86_arch_string, "Generate code for given CPU"}, \
|
||||
{ "reg-alloc=", &i386_reg_alloc_order, "Control allocation order of integer registers" }, \
|
||||
{ "regparm=", &i386_regparm_string, "Number of registers used to pass integer arguments" }, \
|
||||
{ "align-loops=", &i386_align_loops_string, "Loop code aligned to this power of 2" }, \
|
||||
{ "align-jumps=", &i386_align_jumps_string, "Jump targets are aligned to this power of 2" }, \
|
||||
{ "align-functions=", &i386_align_funcs_string, "Function starts are aligned to this power of 2" }, \
|
||||
{ "preferred-stack-boundary=", &i386_preferred_stack_boundary_string, "Attempt to keep stack aligned to this power of 2" }, \
|
||||
{ "branch-cost=", &i386_branch_cost_string, "Branches are this expensive (1-5, arbitrary units)" }, \
|
||||
SUBTARGET_OPTIONS \
|
||||
}
|
||||
|
||||
@ -295,44 +294,45 @@ extern int ix86_arch;
|
||||
#define CC1_CPU_SPEC "\
|
||||
%{!mcpu*: \
|
||||
%{m386:-mcpu=i386 -march=i386} \
|
||||
%{mno-486:-mcpu=i386 -march=i386} \
|
||||
%{m486:-mcpu=i486 -march=i486} \
|
||||
%{mno-386:-mcpu=i486 -march=i486} \
|
||||
%{mno-pentium:-mcpu=i486 -march=i486} \
|
||||
%{mpentium:-mcpu=pentium} \
|
||||
%{mno-pentiumpro:-mcpu=pentium} \
|
||||
%{mpentiumpro:-mcpu=pentiumpro}}"
|
||||
#endif
|
||||
|
||||
#define CPP_486_SPEC "%{!ansi:-Di486} -D__i486 -D__i486__"
|
||||
#define CPP_586_SPEC "%{!ansi:-Di586 -Dpentium} \
|
||||
-D__i586 -D__i586__ -D__pentium -D__pentium__"
|
||||
#define CPP_K6_SPEC "%{!ansi:-Di586 -Dk6} \
|
||||
-D__i586 -D__i586__ -D__k6 -D__k6__"
|
||||
#define CPP_686_SPEC "%{!ansi:-Di686 -Dpentiumpro} \
|
||||
-D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__"
|
||||
|
||||
#ifndef CPP_CPU_DEFAULT_SPEC
|
||||
#if TARGET_CPU_DEFAULT == 1
|
||||
#define CPP_CPU_DEFAULT_SPEC "%(cpp_486)"
|
||||
#else
|
||||
#endif
|
||||
#if TARGET_CPU_DEFAULT == 2
|
||||
#define CPP_CPU_DEFAULT_SPEC "%(cpp_586)"
|
||||
#else
|
||||
#endif
|
||||
#if TARGET_CPU_DEFAULT == 3
|
||||
#define CPP_CPU_DEFAULT_SPEC "%(cpp_686)"
|
||||
#else
|
||||
#endif
|
||||
#if TARGET_CPU_DEFAULT == 4
|
||||
#define CPP_CPU_DEFAULT_SPEC "%(cpp_k6)"
|
||||
#endif
|
||||
#ifndef CPP_CPU_DEFAULT_SPEC
|
||||
#define CPP_CPU_DEFAULT_SPEC ""
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif /* CPP_CPU_DEFAULT_SPEC */
|
||||
|
||||
#ifndef CPP_CPU_SPEC
|
||||
#define CPP_CPU_SPEC "\
|
||||
-Asystem(unix) -Acpu(i386) -Amachine(i386) \
|
||||
-Acpu(i386) -Amachine(i386) \
|
||||
%{!ansi:-Di386} -D__i386 -D__i386__ \
|
||||
%{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} \
|
||||
%{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} \
|
||||
%{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} \
|
||||
%{mcpu=k6:%(cpp_k6)} \
|
||||
%{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}"
|
||||
#endif
|
||||
|
||||
@ -357,6 +357,7 @@ extern int ix86_arch;
|
||||
#define EXTRA_SPECS \
|
||||
{ "cpp_486", CPP_486_SPEC}, \
|
||||
{ "cpp_586", CPP_586_SPEC}, \
|
||||
{ "cpp_k6", CPP_K6_SPEC}, \
|
||||
{ "cpp_686", CPP_686_SPEC}, \
|
||||
{ "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \
|
||||
{ "cpp_cpu", CPP_CPU_SPEC }, \
|
||||
@ -407,9 +408,13 @@ extern int ix86_arch;
|
||||
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
|
||||
#define PARM_BOUNDARY 32
|
||||
|
||||
/* Boundary (in *bits*) on which stack pointer should be aligned. */
|
||||
/* Boundary (in *bits*) on which the stack pointer must be aligned. */
|
||||
#define STACK_BOUNDARY 32
|
||||
|
||||
/* Boundary (in *bits*) on which the stack pointer preferrs to be
|
||||
aligned; the compiler cannot rely on having this alignment. */
|
||||
#define PREFERRED_STACK_BOUNDARY i386_preferred_stack_boundary
|
||||
|
||||
/* Allocation boundary (in *bits*) for the code of a function.
|
||||
For i486, we get better performance by aligning to a cache
|
||||
line (i.e. 16 byte) boundary. */
|
||||
@ -502,6 +507,46 @@ extern int ix86_arch;
|
||||
: (ALIGN)) \
|
||||
: (ALIGN))
|
||||
|
||||
/* If defined, a C expression to compute the alignment for a local
|
||||
variable. TYPE is the data type, and ALIGN is the alignment that
|
||||
the object would ordinarily have. The value of this macro is used
|
||||
instead of that alignment to align the object.
|
||||
|
||||
If this macro is not defined, then ALIGN is used.
|
||||
|
||||
One use of this macro is to increase alignment of medium-size
|
||||
data to make it all fit in fewer cache lines. */
|
||||
|
||||
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
|
||||
(TREE_CODE (TYPE) == ARRAY_TYPE \
|
||||
? ((TYPE_MODE (TREE_TYPE (TYPE)) == DFmode && (ALIGN) < 64) \
|
||||
? 64 \
|
||||
: (TYPE_MODE (TREE_TYPE (TYPE)) == XFmode && (ALIGN) < 128) \
|
||||
? 128 \
|
||||
: (ALIGN)) \
|
||||
: TREE_CODE (TYPE) == COMPLEX_TYPE \
|
||||
? ((TYPE_MODE (TYPE) == DCmode && (ALIGN) < 64) \
|
||||
? 64 \
|
||||
: (TYPE_MODE (TYPE) == XCmode && (ALIGN) < 128) \
|
||||
? 128 \
|
||||
: (ALIGN)) \
|
||||
: ((TREE_CODE (TYPE) == RECORD_TYPE \
|
||||
|| TREE_CODE (TYPE) == UNION_TYPE \
|
||||
|| TREE_CODE (TYPE) == QUAL_UNION_TYPE) \
|
||||
&& TYPE_FIELDS (TYPE)) \
|
||||
? ((DECL_MODE (TYPE_FIELDS (TYPE)) == DFmode && (ALIGN) < 64) \
|
||||
? 64 \
|
||||
: (DECL_MODE (TYPE_FIELDS (TYPE)) == XFmode && (ALIGN) < 128) \
|
||||
? 128 \
|
||||
: (ALIGN)) \
|
||||
: TREE_CODE (TYPE) == REAL_TYPE \
|
||||
? ((TYPE_MODE (TYPE) == DFmode && (ALIGN) < 64) \
|
||||
? 64 \
|
||||
: (TYPE_MODE (TYPE) == XFmode && (ALIGN) < 128) \
|
||||
? 128 \
|
||||
: (ALIGN)) \
|
||||
: (ALIGN))
|
||||
|
||||
/* Set this non-zero if move instructions will actually fail to work
|
||||
when given unaligned data. */
|
||||
#define STRICT_ALIGNMENT 0
|
||||
@ -664,8 +709,8 @@ extern int ix86_arch;
|
||||
|
||||
#define MODES_TIEABLE_P(MODE1, MODE2) \
|
||||
((MODE1) == (MODE2) \
|
||||
|| ((MODE1) == SImode && (MODE2) == HImode \
|
||||
|| (MODE1) == HImode && (MODE2) == SImode))
|
||||
|| ((MODE1) == SImode && (MODE2) == HImode) \
|
||||
|| ((MODE1) == HImode && (MODE2) == SImode))
|
||||
|
||||
/* Specify the registers used for certain standard purposes.
|
||||
The values of these macros are register numbers. */
|
||||
@ -834,11 +879,6 @@ enum reg_class
|
||||
|
||||
#define STACK_TOP_P(xop) (REG_P (xop) && REGNO (xop) == FIRST_STACK_REG)
|
||||
|
||||
/* Try to maintain the accuracy of the death notes for regs satisfying the
|
||||
following. Important for stack like regs, to know when to pop. */
|
||||
|
||||
/* #define PRESERVE_DEATH_INFO_REGNO_P(x) FP_REGNO_P(x) */
|
||||
|
||||
/* 1 if register REGNO can magically overlap other regs.
|
||||
Note that nonzero values work only in very special circumstances. */
|
||||
|
||||
@ -896,19 +936,10 @@ enum reg_class
|
||||
/* Similar, but for floating constants, and defining letters G and H.
|
||||
Here VALUE is the CONST_DOUBLE rtx itself. We allow constants even if
|
||||
TARGET_387 isn't set, because the stack register converter may need to
|
||||
load 0.0 into the function value register.
|
||||
|
||||
We disallow these constants when -fomit-frame-pointer and compiling
|
||||
PIC code since reload might need to force the constant to memory.
|
||||
Forcing the constant to memory changes the elimination offsets after
|
||||
the point where they must stay constant.
|
||||
|
||||
However, we must allow them after reload as completed as reg-stack.c
|
||||
will create insns which use these constants. */
|
||||
load 0.0 into the function value register. */
|
||||
|
||||
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
|
||||
(((reload_completed || !flag_pic || !flag_omit_frame_pointer) && (C) == 'G') \
|
||||
? standard_80387_constant_p (VALUE) : 0)
|
||||
((C) == 'G' ? standard_80387_constant_p (VALUE) : 0)
|
||||
|
||||
/* Place additional restrictions on the register class to use when it
|
||||
is necessary to be able to hold a value of mode MODE in a reload
|
||||
@ -931,8 +962,11 @@ enum reg_class
|
||||
Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and
|
||||
movdf to do mem-to-mem moves through integer regs. */
|
||||
|
||||
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
|
||||
(GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode ? NO_REGS \
|
||||
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
|
||||
(GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != VOIDmode \
|
||||
? (standard_80387_constant_p (X) \
|
||||
? reg_class_subset_p (CLASS, FLOAT_REGS) ? CLASS : FLOAT_REGS \
|
||||
: NO_REGS) \
|
||||
: GET_MODE (X) == QImode && ! reg_class_subset_p (CLASS, Q_REGS) ? Q_REGS \
|
||||
: ((CLASS) == ALL_REGS \
|
||||
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) ? GENERAL_REGS \
|
||||
@ -1532,25 +1566,16 @@ do { \
|
||||
/* Output assembler code for a block containing the constant parts
|
||||
of a trampoline, leaving space for the variable parts. */
|
||||
|
||||
/* On the 386, the trampoline contains three instructions:
|
||||
/* On the 386, the trampoline contains two instructions:
|
||||
mov #STATIC,ecx
|
||||
mov #FUNCTION,eax
|
||||
jmp @eax */
|
||||
#define TRAMPOLINE_TEMPLATE(FILE) \
|
||||
{ \
|
||||
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb9)); \
|
||||
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
|
||||
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
|
||||
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xb8)); \
|
||||
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
|
||||
ASM_OUTPUT_SHORT (FILE, const0_rtx); \
|
||||
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xff)); \
|
||||
ASM_OUTPUT_CHAR (FILE, GEN_INT (0xe0)); \
|
||||
}
|
||||
jmp FUNCTION
|
||||
The trampoline is generated entirely at runtime. The operand of JMP
|
||||
is the address of FUNCTION relative to the instruction following the
|
||||
JMP (which is 5 bytes long). */
|
||||
|
||||
/* Length in units of the trampoline for entering a nested function. */
|
||||
|
||||
#define TRAMPOLINE_SIZE 12
|
||||
#define TRAMPOLINE_SIZE 10
|
||||
|
||||
/* Emit RTL insns to initialize the variable parts of a trampoline.
|
||||
FNADDR is an RTX for the address of the function's pure code.
|
||||
@ -1558,8 +1583,14 @@ do { \
|
||||
|
||||
#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
|
||||
{ \
|
||||
/* Compute offset from the end of the jmp to the target function. */ \
|
||||
rtx disp = expand_binop (SImode, sub_optab, FNADDR, \
|
||||
plus_constant (TRAMP, 10), \
|
||||
NULL_RTX, 1, OPTAB_DIRECT); \
|
||||
emit_move_insn (gen_rtx_MEM (QImode, TRAMP), GEN_INT (0xb9)); \
|
||||
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \
|
||||
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), FNADDR); \
|
||||
emit_move_insn (gen_rtx_MEM (QImode, plus_constant (TRAMP, 5)), GEN_INT (0xe9));\
|
||||
emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), disp); \
|
||||
}
|
||||
|
||||
/* Definitions for register eliminations.
|
||||
@ -1601,30 +1632,33 @@ do { \
|
||||
(OFFSET) = 8; /* Skip saved PC and previous frame pointer */ \
|
||||
else \
|
||||
{ \
|
||||
int regno; \
|
||||
int offset = 0; \
|
||||
int nregs; \
|
||||
int offset; \
|
||||
int preferred_alignment = PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT; \
|
||||
HOST_WIDE_INT tsize = ix86_compute_frame_size (get_frame_size (), \
|
||||
&nregs); \
|
||||
\
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
|
||||
if ((regs_ever_live[regno] && ! call_used_regs[regno]) \
|
||||
|| ((current_function_uses_pic_offset_table \
|
||||
|| current_function_uses_const_pool) \
|
||||
&& flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)) \
|
||||
offset += 4; \
|
||||
(OFFSET) = (tsize + nregs * UNITS_PER_WORD); \
|
||||
\
|
||||
(OFFSET) = offset + get_frame_size (); \
|
||||
offset = 4; \
|
||||
if (frame_pointer_needed) \
|
||||
offset += UNITS_PER_WORD; \
|
||||
\
|
||||
if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
|
||||
(OFFSET) += 4; /* Skip saved PC */ \
|
||||
if ((FROM) == ARG_POINTER_REGNUM) \
|
||||
(OFFSET) += offset; \
|
||||
else \
|
||||
(OFFSET) -= ((offset + preferred_alignment - 1) \
|
||||
& -preferred_alignment) - offset; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
|
||||
/* #define HAVE_POST_INCREMENT */
|
||||
/* #define HAVE_POST_DECREMENT */
|
||||
/* #define HAVE_POST_INCREMENT 0 */
|
||||
/* #define HAVE_POST_DECREMENT 0 */
|
||||
|
||||
/* #define HAVE_PRE_DECREMENT */
|
||||
/* #define HAVE_PRE_INCREMENT */
|
||||
/* #define HAVE_PRE_DECREMENT 0 */
|
||||
/* #define HAVE_PRE_INCREMENT 0 */
|
||||
|
||||
/* Macros to check register numbers against specific register classes. */
|
||||
|
||||
@ -1703,15 +1737,15 @@ do { \
|
||||
|
||||
#define MAX_REGS_PER_ADDRESS 2
|
||||
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|
||||
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST \
|
||||
|| GET_CODE (X) == HIGH)
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF \
|
||||
|| GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST)
|
||||
|
||||
/* Nonzero if the constant value X is a legitimate general operand.
|
||||
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
|
||||
|
||||
#define LEGITIMATE_CONSTANT_P(X) 1
|
||||
#define LEGITIMATE_CONSTANT_P(X) \
|
||||
(GET_CODE (X) == CONST_DOUBLE ? standard_80387_constant_p (X) : 1)
|
||||
|
||||
#ifdef REG_OK_STRICT
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
@ -1764,8 +1798,7 @@ do { \
|
||||
that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
|
||||
|
||||
#define LEGITIMATE_PIC_OPERAND_P(X) \
|
||||
(! SYMBOLIC_CONST (X) \
|
||||
|| (GET_CODE (X) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (X)))
|
||||
(! SYMBOLIC_CONST (X) || legitimate_pic_address_disp_p (X))
|
||||
|
||||
#define SYMBOLIC_CONST(X) \
|
||||
(GET_CODE (X) == SYMBOL_REF \
|
||||
@ -1893,10 +1926,10 @@ while (0)
|
||||
in one reasonably fast instruction. */
|
||||
#define MOVE_MAX 4
|
||||
|
||||
/* The number of scalar move insns which should be generated instead
|
||||
of a string move insn or a library call. Increasing the value
|
||||
will always make code faster, but eventually incurs high cost in
|
||||
increased code size.
|
||||
/* If a memory-to-memory move would take MOVE_RATIO or more simple
|
||||
move-instruction pairs, we will do a movstr or libcall instead.
|
||||
Increasing the value will always make code faster, but eventually
|
||||
incurs high cost in increased code size.
|
||||
|
||||
If you don't define this, a reasonable default is used.
|
||||
|
||||
@ -2243,70 +2276,7 @@ while (0)
|
||||
the same cost as a data-dependence. */
|
||||
|
||||
#define ADJUST_COST(insn,link,dep_insn,cost) \
|
||||
{ \
|
||||
rtx next_inst; \
|
||||
if (GET_CODE (dep_insn) == CALL_INSN) \
|
||||
(cost) = 0; \
|
||||
\
|
||||
else if (GET_CODE (dep_insn) == INSN \
|
||||
&& GET_CODE (PATTERN (dep_insn)) == SET \
|
||||
&& GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG \
|
||||
&& GET_CODE (insn) == INSN \
|
||||
&& GET_CODE (PATTERN (insn)) == SET \
|
||||
&& !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)), \
|
||||
SET_SRC (PATTERN (insn)))) \
|
||||
{ \
|
||||
(cost) = 0; \
|
||||
} \
|
||||
\
|
||||
else if (GET_CODE (insn) == JUMP_INSN) \
|
||||
{ \
|
||||
(cost) = 0; \
|
||||
} \
|
||||
\
|
||||
if (TARGET_PENTIUM) \
|
||||
{ \
|
||||
if (cost !=0 && is_fp_insn (insn) && is_fp_insn (dep_insn) \
|
||||
&& !is_fp_dest (dep_insn)) \
|
||||
{ \
|
||||
(cost) = 0; \
|
||||
} \
|
||||
\
|
||||
if (agi_dependent (insn, dep_insn)) \
|
||||
{ \
|
||||
(cost) = 3; \
|
||||
} \
|
||||
else if (GET_CODE (insn) == INSN \
|
||||
&& GET_CODE (PATTERN (insn)) == SET \
|
||||
&& SET_DEST (PATTERN (insn)) == cc0_rtx \
|
||||
&& (next_inst = next_nonnote_insn (insn)) \
|
||||
&& GET_CODE (next_inst) == JUMP_INSN) \
|
||||
{ /* compare probably paired with jump */ \
|
||||
(cost) = 0; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
if (!is_fp_dest (dep_insn)) \
|
||||
{ \
|
||||
if(!agi_dependent (insn, dep_insn)) \
|
||||
(cost) = 0; \
|
||||
else if (TARGET_486) \
|
||||
(cost) = 2; \
|
||||
} \
|
||||
else \
|
||||
if (is_fp_store (insn) && is_fp_insn (dep_insn) \
|
||||
&& NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn)) \
|
||||
&& NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))) \
|
||||
&& (GET_CODE (NEXT_INSN (insn)) == INSN) \
|
||||
&& (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN) \
|
||||
&& (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) == NOTE) \
|
||||
&& (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) \
|
||||
== NOTE_INSN_LOOP_END)) \
|
||||
{ \
|
||||
(cost) = 3; \
|
||||
} \
|
||||
}
|
||||
|
||||
(cost) = x86_adjust_cost(insn, link, dep_insn, cost)
|
||||
|
||||
#define ADJUST_BLOCKAGE(last_insn,insn,blockage) \
|
||||
{ \
|
||||
@ -2323,6 +2293,8 @@ while (0)
|
||||
} \
|
||||
}
|
||||
|
||||
#define ISSUE_RATE ((int)ix86_cpu > (int)PROCESSOR_I486 ? 2 : 1)
|
||||
|
||||
|
||||
/* Add any extra modes needed to represent the condition code.
|
||||
|
||||
@ -2606,7 +2578,7 @@ do { long l; \
|
||||
F,f -- likewise, but for floating-point. */
|
||||
|
||||
#define PRINT_OPERAND_PUNCT_VALID_P(CODE) \
|
||||
((CODE) == '*')
|
||||
((CODE) == '*' || (CODE) == '_')
|
||||
|
||||
/* Print the name of a register based on its machine mode and number.
|
||||
If CODE is 'w', pretend the mode is HImode.
|
||||
@ -2741,11 +2713,8 @@ extern void function_arg_advance ();
|
||||
extern struct rtx_def *function_arg ();
|
||||
extern int function_arg_partial_nregs ();
|
||||
extern char *output_strlen_unroll ();
|
||||
extern void output_op_from_reg ();
|
||||
extern void output_to_reg ();
|
||||
extern char *singlemove_string ();
|
||||
extern char *output_move_double ();
|
||||
extern char *output_move_memory ();
|
||||
extern char *output_move_pushmem ();
|
||||
extern int standard_80387_constant_p ();
|
||||
extern char *output_move_const_single ();
|
||||
@ -2773,6 +2742,7 @@ extern int shift_op ();
|
||||
extern int VOIDmode_compare_op ();
|
||||
extern char *output_387_binary_op ();
|
||||
extern char *output_fix_trunc ();
|
||||
extern void output_float_extend ();
|
||||
extern char *output_float_compare ();
|
||||
extern char *output_fp_cc0_set ();
|
||||
extern void save_386_machine_status ();
|
||||
@ -2793,6 +2763,9 @@ extern int reg_mentioned_in_mem ();
|
||||
extern char *output_int_conditional_move ();
|
||||
extern char *output_fp_conditional_move ();
|
||||
extern int ix86_can_use_return_insn_p ();
|
||||
extern int small_shift_operand ();
|
||||
extern char *output_ashl ();
|
||||
extern int memory_address_info ();
|
||||
|
||||
#ifdef NOTYET
|
||||
extern struct rtx_def *copy_all_rtx ();
|
||||
@ -2807,11 +2780,13 @@ extern char *i386_regparm_string; /* # registers to use to pass args */
|
||||
extern char *i386_align_loops_string; /* power of two alignment for loops */
|
||||
extern char *i386_align_jumps_string; /* power of two alignment for non-loop jumps */
|
||||
extern char *i386_align_funcs_string; /* power of two alignment for functions */
|
||||
extern char *i386_preferred_stack_boundary_string;/* power of two alignment for stack boundary */
|
||||
extern char *i386_branch_cost_string; /* values 1-5: see jump.c */
|
||||
extern int i386_regparm; /* i386_regparm_string as a number */
|
||||
extern int i386_align_loops; /* power of two alignment for loops */
|
||||
extern int i386_align_jumps; /* power of two alignment for non-loop jumps */
|
||||
extern int i386_align_funcs; /* power of two alignment for functions */
|
||||
extern int i386_preferred_stack_boundary; /* preferred stack boundary alignment in bits */
|
||||
extern int i386_branch_cost; /* values 1-5: see jump.c */
|
||||
extern char *hi_reg_name[]; /* names for 16 bit regs */
|
||||
extern char *qi_reg_name[]; /* names for 8 bit regs (low) */
|
||||
|
File diff suppressed because it is too large
Load Diff
110
contrib/gcc/config/i386/interix.c
Normal file
110
contrib/gcc/config/i386/interix.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* Subroutines for insn-output.c for Windows NT.
|
||||
Copyright (C) 1998, 1999 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. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "rtl.h"
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "output.h"
|
||||
#include "tree.h"
|
||||
#include "flags.h"
|
||||
|
||||
/* Return string which is the former assembler name modified with a
|
||||
suffix consisting of an atsign (@) followed by the number of bytes of
|
||||
arguments */
|
||||
|
||||
char *
|
||||
gen_stdcall_suffix (decl)
|
||||
tree decl;
|
||||
{
|
||||
int total = 0;
|
||||
/* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
|
||||
of DECL_ASSEMBLER_NAME. */
|
||||
char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
char *newsym;
|
||||
|
||||
if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
|
||||
if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
|
||||
== void_type_node)
|
||||
{
|
||||
tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
|
||||
|
||||
while (TREE_VALUE (formal_type) != void_type_node)
|
||||
{
|
||||
int parm_size
|
||||
= TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
|
||||
/* Must round up to include padding. This is done the same
|
||||
way as in store_one_arg. */
|
||||
parm_size = ((parm_size + PARM_BOUNDARY - 1)
|
||||
/ PARM_BOUNDARY * PARM_BOUNDARY);
|
||||
total += parm_size;
|
||||
formal_type = TREE_CHAIN (formal_type);
|
||||
}
|
||||
}
|
||||
|
||||
newsym = xmalloc (strlen (asmname) + 10);
|
||||
sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
|
||||
return IDENTIFIER_POINTER (get_identifier (newsym));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Turn this back on when the linker is updated to handle grouped
|
||||
.data$ sections correctly. See corresponding note in i386/interix.h.
|
||||
MK. */
|
||||
|
||||
/* Cover function for UNIQUE_SECTION. */
|
||||
|
||||
void
|
||||
i386_pe_unique_section (decl, reloc)
|
||||
tree decl;
|
||||
int reloc;
|
||||
{
|
||||
int len;
|
||||
char *name,*string,*prefix;
|
||||
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
/* Strip off any encoding in fnname. */
|
||||
STRIP_NAME_ENCODING (name, name);
|
||||
|
||||
/* The object is put in, for example, section .text$foo.
|
||||
The linker will then ultimately place them in .text
|
||||
(everything from the $ on is stripped). Don't put
|
||||
read-only data in .rdata section to avoid a PE linker
|
||||
bug when .rdata$* grouped sections are used in code
|
||||
without a .rdata section. */
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
prefix = ".text$";
|
||||
else if (DECL_READONLY_SECTION (decl, reloc))
|
||||
#ifdef READONLY_DATA_SECTION
|
||||
prefix = ".rdata$";
|
||||
#else
|
||||
prefix = ".text$";
|
||||
#endif
|
||||
else
|
||||
prefix = ".data$";
|
||||
len = strlen (name) + strlen (prefix);
|
||||
string = alloca (len + 1);
|
||||
sprintf (string, "%s%s", prefix, name);
|
||||
|
||||
DECL_SECTION_NAME (decl) = build_string (len, string);
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
@ -59,7 +59,7 @@
|
||||
So don't make TARGET_IEEE_FP default for ISC. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0201
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
|
||||
|
||||
/* The ISC 2.0.2 software FPU emulator apparently can't handle
|
||||
80-bit XFmode insns, so don't generate them. */
|
||||
@ -72,20 +72,23 @@
|
||||
message. */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { \
|
||||
char c; \
|
||||
int max = 0; \
|
||||
char *string = dump_base_name; \
|
||||
\
|
||||
fputs ("\t.file\t\"", FILE); \
|
||||
\
|
||||
while ((c = *string++) != 0 && max++ < 14) { \
|
||||
if (c == '\"' || c == '\\') \
|
||||
putc ('\\', FILE); \
|
||||
putc (c, FILE); \
|
||||
} \
|
||||
fputs ("\"\n", FILE); \
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { \
|
||||
int len = strlen (main_input_filename); \
|
||||
char *na = main_input_filename + len; \
|
||||
char shorter[15]; \
|
||||
/* NA gets MAIN_INPUT_FILENAME sans directory names. */\
|
||||
while (na > main_input_filename) \
|
||||
{ \
|
||||
if (na[-1] == '/') \
|
||||
break; \
|
||||
na--; \
|
||||
} \
|
||||
strncpy (shorter, na, 14); \
|
||||
shorter[14] = 0; \
|
||||
fprintf (FILE, "\t.file\t"); \
|
||||
output_quoted_string (FILE, shorter); \
|
||||
fprintf (FILE, "\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Work around assembler forward label references generated in exception
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* Definitions for Intel 386 running Interactive Unix System V.
|
||||
Specifically, this is for recent versions that support POSIX;
|
||||
for version 2.0.2, use configuration option i386-sysv instead.
|
||||
(But set TARGET_DEFAULT to 0201 if you do that,
|
||||
if you don't have a real 80387.) */
|
||||
(But set TARGET_DEFAULT to (MASK_80307 | MASK_FLOAT_RETURNS)
|
||||
if you do that, if you don't have a real 80387.) */
|
||||
|
||||
/* Mostly it's like AT&T Unix System V. */
|
||||
|
||||
|
@ -150,9 +150,8 @@ Boston, MA 02111-1307, USA. */
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE BITS_PER_WORD
|
||||
|
||||
/* The egcs-1.1 branch is the last time we will have -Di386. -D__i386__ is the thing to use. */
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -Asystem(posix)"
|
||||
#define CPP_PREDEFINES "-D__ELF__ -Dunix -D__i386__ -Dlinux -Asystem(posix)"
|
||||
|
||||
#undef CPP_SPEC
|
||||
#ifdef USE_GNULIBC_1
|
||||
@ -227,8 +226,11 @@ Boston, MA 02111-1307, USA. */
|
||||
This is used to align code labels according to Intel recommendations. */
|
||||
|
||||
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
|
||||
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
if ((LOG)!=0) \
|
||||
if ((MAX_SKIP)==0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP))
|
||||
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
do { \
|
||||
if ((LOG) != 0) { \
|
||||
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
@ -2,7 +2,7 @@
|
||||
hosting on Windows32, using GNU tools and the Windows32 API Library,
|
||||
as distinct from winnt.h, which is used to build GCC for use with a
|
||||
windows style library and tool set and uses the Microsoft tools.
|
||||
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -21,17 +21,17 @@ 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. */
|
||||
|
||||
/* Most of this is the same as for Cygwin32, except for changing some
|
||||
/* Most of this is the same as for cygwin, except for changing some
|
||||
specs. */
|
||||
|
||||
#include "i386/cygwin32.h"
|
||||
#include "i386/cygwin.h"
|
||||
|
||||
/* Please keep changes to CPP_PREDEFINES in sync with i386/crtdll. The
|
||||
only difference between the two should be __MSVCRT__ needed to
|
||||
distinguish MSVC from CRTDLL runtime in mingw headers. */
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \
|
||||
-D__MINGW32__ -D__MSVCRT__ -DWINNT -D_X86_=1 -D__STDC__=1\
|
||||
-D__MINGW32__=0.2 -D__MSVCRT__ -DWINNT -D_X86_=1 -D__STDC__=1\
|
||||
-D__stdcall=__attribute__((__stdcall__)) \
|
||||
-D_stdcall=__attribute__((__stdcall__)) \
|
||||
-D__cdecl=__attribute__((__cdecl__)) \
|
||||
@ -44,25 +44,24 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#define STANDARD_INCLUDE_COMPONENT "MINGW32"
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "-remap %(cpp_cpu) %{posix:-D_POSIX_SOURCE}"
|
||||
|
||||
/* For Windows applications, include more libraries, but always include
|
||||
kernel32. */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC \
|
||||
"%{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32 -lshell32"
|
||||
#define LIB_SPEC "%{mwindows:-lgdi32 -lcomdlg32} \
|
||||
-luser32 -lkernel32 -ladvapi32 -lshell32"
|
||||
|
||||
/* Include in the mingw32 libraries with libgcc */
|
||||
#undef LIBGCC_SPEC
|
||||
#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lmsvcrt"
|
||||
|
||||
/* Specify a different entry point when linking a DLL */
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC \
|
||||
"%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12}"
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "%{mdll:dllcrt2%O%s} %{!mdll:crt2%O%s}"
|
||||
|
||||
#define MATH_LIBRARY "-lmsvcrt"
|
||||
/* MS runtime does not need a separate math library. */
|
||||
#define MATH_LIBRARY ""
|
||||
|
||||
/* Output STRING, a string representing a filename, to FILE. We canonicalize
|
||||
it to be in MS-DOS format. */
|
||||
|
@ -16,7 +16,8 @@ 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* I believe in reuse... */
|
||||
#include "i386/linux.h"
|
||||
|
@ -1,6 +1,3 @@
|
||||
/* This goes away when the math-emulator is fixed */
|
||||
#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */
|
||||
|
||||
/* This is tested by i386gas.h. */
|
||||
#define YES_UNDERSCORES
|
||||
|
||||
@ -12,6 +9,11 @@
|
||||
/* Get generic NetBSD definitions. */
|
||||
#include <netbsd.h>
|
||||
|
||||
/* This goes away when the math-emulator is fixed */
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT \
|
||||
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Dunix -Di386 -D__NetBSD__ -Asystem(unix) -Asystem(NetBSD) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Target definitions for GNU compiler for Intel x86 CPU running NeXTSTEP
|
||||
Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1993, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */
|
||||
/* By default, target has a 80387, with IEEE FP. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT (1|0100)
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP)
|
||||
|
||||
/* Implicit library calls should use memcpy, not bcopy, etc. */
|
||||
|
||||
|
@ -31,6 +31,11 @@ Boston, MA 02111-1307, USA. */
|
||||
#define OBSD_OLD_GAS
|
||||
#include <openbsd.h>
|
||||
|
||||
/* This goes away when the math-emulator is fixed */
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT \
|
||||
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
|
||||
|
||||
/* Run-time target specifications */
|
||||
#define CPP_PREDEFINES "-D__unix__ -D__i386__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
@ -120,9 +125,10 @@ Boston, MA 02111-1307, USA. */
|
||||
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
|
||||
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
do { \
|
||||
if ((LOG) != 0) \
|
||||
if ((LOG) != 0) { \
|
||||
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
@ -121,8 +121,8 @@ extern char *sys_siglist[];
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "mcount", -MASK_NO_MCOUNT}, \
|
||||
{ "no-mcount", MASK_NO_MCOUNT},
|
||||
{ "mcount", -MASK_NO_MCOUNT, "Profiling uses mcount" }, \
|
||||
{ "no-mcount", MASK_NO_MCOUNT, "" },
|
||||
|
||||
/* This macro generates the assembly code for function entry.
|
||||
FILE is a stdio stream to output the code to.
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Definitions of target machine for GNU compiler.
|
||||
Intel 386 (OSF/1 with OSF/rose) version.
|
||||
Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1991, 1992, 1993, 1996, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -43,7 +43,6 @@ Boston, MA 02111-1307, USA. */
|
||||
#define MASK_HALF_PIC 010000000000 /* Mask for half-pic code */
|
||||
#define MASK_HALF_PIC_DEBUG 004000000000 /* Debug flag */
|
||||
#define MASK_ELF 002000000000 /* ELF not rose */
|
||||
#define MASK_NO_IDENT 001000000000 /* suppress .ident */
|
||||
#define MASK_NO_UNDERSCORES 000400000000 /* suppress leading _ */
|
||||
#define MASK_LARGE_ALIGN 000200000000 /* align to >word boundaries */
|
||||
#define MASK_NO_MCOUNT 000100000000 /* profiling uses mcount_ptr */
|
||||
@ -53,28 +52,25 @@ Boston, MA 02111-1307, USA. */
|
||||
#define HALF_PIC_DEBUG TARGET_DEBUG
|
||||
#define TARGET_ELF (target_flags & MASK_ELF)
|
||||
#define TARGET_ROSE ((target_flags & MASK_ELF) == 0)
|
||||
#define TARGET_IDENT ((target_flags & MASK_NO_IDENT) == 0)
|
||||
#define TARGET_UNDERSCORES ((target_flags & MASK_NO_UNDERSCORES) == 0)
|
||||
#define TARGET_LARGE_ALIGN (target_flags & MASK_LARGE_ALIGN)
|
||||
#define TARGET_MCOUNT ((target_flags & MASK_NO_MCOUNT) == 0)
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "half-pic", MASK_HALF_PIC}, \
|
||||
{ "no-half-pic", -MASK_HALF_PIC}, \
|
||||
{ "debug-half-pic", MASK_HALF_PIC_DEBUG}, \
|
||||
{ "debugb", MASK_HALF_PIC_DEBUG}, \
|
||||
{ "elf", MASK_ELF}, \
|
||||
{ "rose", -MASK_ELF}, \
|
||||
{ "ident", -MASK_NO_IDENT}, \
|
||||
{ "no-ident", MASK_NO_IDENT}, \
|
||||
{ "underscores", -MASK_NO_UNDERSCORES}, \
|
||||
{ "no-underscores", MASK_NO_UNDERSCORES}, \
|
||||
{ "large-align", MASK_LARGE_ALIGN}, \
|
||||
{ "no-large-align", -MASK_LARGE_ALIGN}, \
|
||||
{ "mcount", -MASK_NO_MCOUNT}, \
|
||||
{ "mcount-ptr", MASK_NO_MCOUNT}, \
|
||||
{ "no-mcount", MASK_NO_MCOUNT},
|
||||
{ "half-pic", MASK_HALF_PIC, "Emit half-PIC code" }, \
|
||||
{ "no-half-pic", -MASK_HALF_PIC, "" } \
|
||||
{ "debug-half-pic", MASK_HALF_PIC_DEBUG, 0 /* intentionally undoc */ }, \
|
||||
{ "debugb", MASK_HALF_PIC_DEBUG, 0 /* intentionally undoc */ }, \
|
||||
{ "elf", MASK_ELF, "Emit ELF object code" }, \
|
||||
{ "rose", -MASK_ELF, "Emit ROSE object code" }, \
|
||||
{ "underscores", -MASK_NO_UNDERSCORES, "Symbols have a leading underscore" }, \
|
||||
{ "no-underscores", MASK_NO_UNDERSCORES, "" }, \
|
||||
{ "large-align", MASK_LARGE_ALIGN, "Align to >word boundaries" }, \
|
||||
{ "no-large-align", -MASK_LARGE_ALIGN, "" }, \
|
||||
{ "mcount", -MASK_NO_MCOUNT, "Use mcount for profiling" }, \
|
||||
{ "mcount-ptr", MASK_NO_MCOUNT, "Use mcount_ptr for profiling" }, \
|
||||
{ "no-mcount", MASK_NO_MCOUNT, "" },
|
||||
|
||||
/* OSF/rose uses stabs, not dwarf. */
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
@ -752,7 +748,7 @@ do \
|
||||
if (HALF_PIC_P ()) \
|
||||
HALF_PIC_FINISH (STREAM); \
|
||||
\
|
||||
if (TARGET_IDENT) \
|
||||
if (!flag_no_ident) \
|
||||
{ \
|
||||
char *fstart = main_input_filename; \
|
||||
char *fname; \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for Intel 386 running SCO Unix System V.
|
||||
Copyright (C) 1988, 1992, 1994, 1995 Free, 1996 Software Foundation, Inc.
|
||||
Copyright (C) 1988, 92, 94, 95, 96, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -31,7 +31,7 @@ Boston, MA 02111-1307, USA. */
|
||||
So don't make TARGET_IEEE_FP default for SCO. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0201
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
|
||||
|
||||
/* Let's guess that the SCO software FPU emulator can't handle
|
||||
80-bit XFmode insns, so don't generate them. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5.
|
||||
Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 95-98, 1999 Free Software Foundation, Inc.
|
||||
Contributed by Kean Johnston (hug@netcom.com)
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -211,8 +211,9 @@ do { \
|
||||
#undef ASM_FILE_END
|
||||
#define ASM_FILE_END(FILE) \
|
||||
do { \
|
||||
fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \
|
||||
IDENT_ASM_OP, version_string); \
|
||||
if (!flag_no_ident) \
|
||||
fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \
|
||||
IDENT_ASM_OP, version_string); \
|
||||
} while (0)
|
||||
|
||||
#undef ASM_FINISH_DECLARE_OBJECT
|
||||
@ -689,7 +690,9 @@ dtors_section () \
|
||||
#undef SELECT_SECTION
|
||||
#define SELECT_SECTION(DECL,RELOC) \
|
||||
{ \
|
||||
if (TREE_CODE (DECL) == STRING_CST) \
|
||||
if (TARGET_ELF && flag_pic && RELOC) \
|
||||
data_section (); \
|
||||
else if (TREE_CODE (DECL) == STRING_CST) \
|
||||
{ \
|
||||
if (! flag_writable_strings) \
|
||||
const_section (); \
|
||||
@ -698,11 +701,7 @@ dtors_section () \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == VAR_DECL) \
|
||||
{ \
|
||||
if ((TARGET_ELF && flag_pic && RELOC) \
|
||||
|| !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
|
||||
|| !DECL_INITIAL (DECL) \
|
||||
|| (DECL_INITIAL (DECL) != error_mark_node \
|
||||
&& !TREE_CONSTANT (DECL_INITIAL (DECL)))) \
|
||||
if (! DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
data_section (); \
|
||||
else \
|
||||
const_section (); \
|
||||
@ -726,11 +725,19 @@ dtors_section () \
|
||||
&& strcmp (STR, "Tbss"))
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0301
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
|
||||
|
||||
#undef HANDLE_SYSV_PRAGMA
|
||||
#define HANDLE_SYSV_PRAGMA 1
|
||||
|
||||
/* Though OpenServer support .weak in COFF, g++ doesn't play nice with it
|
||||
* so we'll punt on it for now
|
||||
*/
|
||||
#define SUPPORTS_WEAK (TARGET_ELF)
|
||||
#define ASM_WEAKEN_LABEL(FILE,NAME) \
|
||||
do { fputs ("\t.weak\t", FILE); assemble_name (FILE, NAME); \
|
||||
fputc ('\n', FILE); } while (0)
|
||||
|
||||
#undef SCCS_DIRECTIVE
|
||||
#define SCCS_DIRECTIVE 1
|
||||
|
||||
@ -904,11 +911,23 @@ dtors_section () \
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "coff", MASK_COFF }, \
|
||||
{ "elf", -MASK_COFF },
|
||||
{ "coff", MASK_COFF, "Generate COFF output" }, \
|
||||
{ "elf", -MASK_COFF, "Generate ELF output" },
|
||||
|
||||
#define NO_DOLLAR_IN_LABEL
|
||||
|
||||
/* Implicit library calls should use memcpy, not bcopy, etc. They are
|
||||
faster on OpenServer libraries. */
|
||||
|
||||
#define TARGET_MEM_FUNCTIONS
|
||||
|
||||
/* Biggest alignment supported by the object file format of this
|
||||
machine. Use this macro to limit the alignment which can be
|
||||
specified using the `__attribute__ ((aligned (N)))' construct. If
|
||||
not defined, the default value is `BIGGEST_ALIGNMENT'. */
|
||||
|
||||
#define MAX_OFILE_ALIGNMENT (32768*8)
|
||||
|
||||
/*
|
||||
Here comes some major hackery to get the crt stuff to compile properly.
|
||||
Since we can (and do) compile for both COFF and ELF environments, we
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Definitions for Intel 386 running SCO Unix System V,
|
||||
using dbx-in-coff encapsulation.
|
||||
Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1995, 1996, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -32,7 +32,7 @@ Boston, MA 02111-1307, USA. */
|
||||
So don't make TARGET_IEEE_FP default for SCO. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0201
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
|
||||
|
||||
/* Use crt1.o as a startup file and crtn.o as a closing file. */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions for Sequent Intel 386.
|
||||
Copyright (C) 1988, 1994 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988, 1994, 1999 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU CC.
|
||||
|
||||
@ -26,11 +26,10 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* By default, don't use IEEE compatible arithmetic comparisons
|
||||
because the assembler can't handle the fucom insn.
|
||||
Return float values in the 387.
|
||||
(TARGET_80387 | TARGET_FLOAT_RETURNS_IN_80387) */
|
||||
Return float values in the 387. */
|
||||
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT 0201
|
||||
#define TARGET_DEFAULT (MASK_80387 | MASK_FLOAT_RETURNS)
|
||||
|
||||
/* Specify predefined symbols in preprocessor. */
|
||||
|
||||
|
@ -93,3 +93,6 @@ Boston, MA 02111-1307, USA. */
|
||||
|| (CHAR) == 'z')
|
||||
|
||||
#define STDC_0_IN_SYSTEM_HEADERS
|
||||
|
||||
#undef LOCAL_LABEL_PREFIX
|
||||
#define LOCAL_LABEL_PREFIX "."
|
||||
|
@ -59,11 +59,11 @@ do \
|
||||
do { \
|
||||
extern char *version_string, *language_string; \
|
||||
{ \
|
||||
int len = strlen (dump_base_name); \
|
||||
char *na = dump_base_name + len; \
|
||||
int len = strlen (main_input_filename); \
|
||||
char *na = main_input_filename + len; \
|
||||
char shorter[15]; \
|
||||
/* NA gets DUMP_BASE_NAME sans directory names. */\
|
||||
while (na > dump_base_name) \
|
||||
/* NA gets MAIN_INPUT_FILENAME sans directory names. */\
|
||||
while (na > main_input_filename) \
|
||||
{ \
|
||||
if (na[-1] == '/') \
|
||||
break; \
|
||||
|
35
contrib/gcc/config/i386/sysv5.h
Normal file
35
contrib/gcc/config/i386/sysv5.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Definitions for Intel 386 running System V Release 5 (i.e. UnixWare 7)
|
||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
||||
Contributed by Robert Lipe (robertlipe@usa.net)
|
||||
|
||||
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. */
|
||||
|
||||
|
||||
#include "i386/sysv4.h"
|
||||
|
||||
/* Dwarf2 is supported by native debuggers */
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
|
||||
|
||||
/* Add -lcrt for Dwarf2 abbreviation table */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "%{pthread:-lthread} %{!shared:%{!symbolic:-lc -lcrt}}"
|
||||
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "%{pthread:-D_REENTRANT}"
|
16
contrib/gcc/config/i386/t-cygwin
Normal file
16
contrib/gcc/config/i386/t-cygwin
Normal file
@ -0,0 +1,16 @@
|
||||
LIBGCC1 = libgcc1-asm.a
|
||||
CROSS_LIBGCC1 = libgcc1-asm.a
|
||||
LIB1ASMSRC = i386/cygwin.asm
|
||||
LIB1ASMFUNCS = _chkstk
|
||||
|
||||
# cygwin always has a limits.h, but, depending upon how we are doing
|
||||
# the build, it may not be installed yet.
|
||||
LIMITS_H_TEST = true
|
||||
|
||||
# If we are building next to winsup, this will let us find the real
|
||||
# limits.h when building libgcc2. Otherwise, winsup must be installed
|
||||
# first.
|
||||
LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/include
|
||||
|
||||
winnt.o: $(srcdir)/config/i386/winnt.c
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
|
@ -1,4 +1,8 @@
|
||||
#
|
||||
# target makefile for dgux
|
||||
#
|
||||
EXTRA_PARTS=crtbegin.o crtend.o
|
||||
EXTRA_PARTS=crti.o crtbegin.o crtend.o
|
||||
|
||||
crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES)
|
||||
sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s
|
||||
$(GCC_FOR_TARGET) -c -o crti.o crti.s
|
||||
|
2
contrib/gcc/config/i386/t-djgpp
Normal file
2
contrib/gcc/config/i386/t-djgpp
Normal file
@ -0,0 +1,2 @@
|
||||
LIBGCC1 = libgcc1.null
|
||||
CROSS_LIBGCC1 = libgcc1.null
|
16
contrib/gcc/config/i386/t-interix
Normal file
16
contrib/gcc/config/i386/t-interix
Normal file
@ -0,0 +1,16 @@
|
||||
# t-interix
|
||||
LIBGCC1 = libgcc1-asm.a
|
||||
CROSS_LIBGCC1 = libgcc1-asm.a
|
||||
|
||||
LIB1ASMSRC = i386/cygwin.asm
|
||||
LIB1ASMFUNCS = _chkstk
|
||||
|
||||
interix.o: $(srcdir)/config/i386/interix.c
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/interix.c
|
||||
|
||||
# System headers will track gcc's needs.
|
||||
# Even LANG_EXTRA_HEADERS may be temporary.
|
||||
USER_H=$(LANG_EXTRA_HEADERS)
|
||||
|
||||
# We don't want this one either.
|
||||
INSTALL_ASSERT_H=
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user