This commit was generated by cvs2svn to compensate for changes in r169689,
which included commits to RCS files with non-trunk default branches.
This commit is contained in:
commit
533952614f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=169690
1
contrib/gcc/BASE-VER
Normal file
1
contrib/gcc/BASE-VER
Normal file
@ -0,0 +1 @@
|
||||
4.2.0
|
@ -2,7 +2,7 @@
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -305,7 +305,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
@ -2,7 +2,7 @@
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -485,7 +485,7 @@ convey the exclusion of warranty; and each file should have at least the
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
10115
contrib/gcc/ChangeLog
10115
contrib/gcc/ChangeLog
File diff suppressed because it is too large
Load Diff
3969
contrib/gcc/ChangeLog-1997
Normal file
3969
contrib/gcc/ChangeLog-1997
Normal file
File diff suppressed because it is too large
Load Diff
17616
contrib/gcc/ChangeLog-1998
Normal file
17616
contrib/gcc/ChangeLog-1998
Normal file
File diff suppressed because it is too large
Load Diff
21786
contrib/gcc/ChangeLog-1999
Normal file
21786
contrib/gcc/ChangeLog-1999
Normal file
File diff suppressed because it is too large
Load Diff
32124
contrib/gcc/ChangeLog-2000
Normal file
32124
contrib/gcc/ChangeLog-2000
Normal file
File diff suppressed because it is too large
Load Diff
33645
contrib/gcc/ChangeLog-2001
Normal file
33645
contrib/gcc/ChangeLog-2001
Normal file
File diff suppressed because it is too large
Load Diff
35988
contrib/gcc/ChangeLog-2002
Normal file
35988
contrib/gcc/ChangeLog-2002
Normal file
File diff suppressed because it is too large
Load Diff
37862
contrib/gcc/ChangeLog-2003
Normal file
37862
contrib/gcc/ChangeLog-2003
Normal file
File diff suppressed because it is too large
Load Diff
47880
contrib/gcc/ChangeLog-2004
Normal file
47880
contrib/gcc/ChangeLog-2004
Normal file
File diff suppressed because it is too large
Load Diff
35909
contrib/gcc/ChangeLog-2005
Normal file
35909
contrib/gcc/ChangeLog-2005
Normal file
File diff suppressed because it is too large
Load Diff
16726
contrib/gcc/ChangeLog-2006
Normal file
16726
contrib/gcc/ChangeLog-2006
Normal file
File diff suppressed because it is too large
Load Diff
19338
contrib/gcc/ChangeLog.tree-ssa
Normal file
19338
contrib/gcc/ChangeLog.tree-ssa
Normal file
File diff suppressed because it is too large
Load Diff
1
contrib/gcc/DATESTAMP
Normal file
1
contrib/gcc/DATESTAMP
Normal file
@ -0,0 +1 @@
|
||||
20070514
|
0
contrib/gcc/DEV-PHASE
Normal file
0
contrib/gcc/DEV-PHASE
Normal file
@ -6,60 +6,24 @@ 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.
|
||||
|
||||
2004-09-09:
|
||||
In an effort to decrease execution time, single char tree code
|
||||
classes were changed to enumerated values.
|
||||
|
||||
Old way:
|
||||
|
||||
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0)
|
||||
|
||||
New way:
|
||||
|
||||
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", tcc_declaration, 0)
|
||||
|
||||
2001-02-26:
|
||||
A DECL_INITIAL of NULL_TREE or error_mark_node in a VAR_DECL is no longer
|
||||
taken to signify a tentative definition which should not be emitted until
|
||||
end-of-file. Frontends which want that behavior should set
|
||||
DECL_DEFER_OUTPUT before calling rest_of_decl_compilation.
|
||||
|
||||
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
|
||||
nonzero 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
|
||||
declaration is: int lang_decode_option (int argc, char** argv). It now
|
||||
returns the number of input strings processed, or 0 if the option is
|
||||
unknown.
|
||||
|
||||
Jun 7, 1998:
|
||||
Front-ends must now define lang_init_options. It is safe for this
|
||||
function to do nothing. See c-lang.c.
|
||||
|
||||
Apr 21, 1998:
|
||||
Front ends which link with c-common or other files from the C/C++
|
||||
front-ends may need to handle TI types. Look for references to
|
||||
[unsigned]int_DI_type_node in your front end. If you have references
|
||||
to these variables, you'll need up update the front end.
|
||||
|
||||
To update the front end you must mirror all the code which currently
|
||||
deals with intDI_type_node to also handle intTI_type_node.
|
||||
|
||||
|
||||
Apr 7, 1998:
|
||||
The interface between toplev.c and the language front ends for opening the
|
||||
source file has changed:
|
||||
|
||||
o init_lex() has been renamed to init_parse (char *filename) where filename
|
||||
is the name of the source file.
|
||||
o The code in toplev.c which opened the source file should be moved to
|
||||
the new init_parse function.
|
||||
o toplev.c now calls finish_parse() instead of closing the source file
|
||||
using fclose(). This should now be done in finish_parse, if necessary.
|
||||
|
||||
Apr 1, 1998:
|
||||
Front-ends must now define lang_print_xnode. It is safe for this
|
||||
function to do nothing. See c-lang.c.
|
||||
|
||||
Feb 1, 1998:
|
||||
|
||||
GCC used to store structure sizes & offsets to elements as bitsize
|
||||
@ -78,10 +42,6 @@ Feb 1, 1998:
|
||||
When a size in bits is converted into a size in bytes, which is expressed
|
||||
in trees, care should be taken to change the tree's type again to sizetype.
|
||||
|
||||
We've updated C, C++, Fortran & Objective-C to work with the new
|
||||
scheme. Other languages will need to be updated accordingly.
|
||||
Contact amylaar@cygnus.com for additional information.
|
||||
|
||||
?? 1997:
|
||||
|
||||
In an effort to decrease cache thrashing and useless loads we've changed the
|
||||
|
512
contrib/gcc/acinclude.m4
Normal file
512
contrib/gcc/acinclude.m4
Normal file
@ -0,0 +1,512 @@
|
||||
dnl See whether we need a declaration for a function.
|
||||
dnl The result is highly dependent on the INCLUDES passed in, so make sure
|
||||
dnl to use a different cache variable name in this macro if it is invoked
|
||||
dnl in a different context somewhere else.
|
||||
dnl gcc_AC_CHECK_DECL(SYMBOL,
|
||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
|
||||
AC_DEFUN([gcc_AC_CHECK_DECL],
|
||||
[AC_MSG_CHECKING([whether $1 is declared])
|
||||
AC_CACHE_VAL(gcc_cv_have_decl_$1,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$4],
|
||||
[#ifndef $1
|
||||
char *(*pfn) = (char *(*)) $1 ;
|
||||
#endif])], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")])
|
||||
if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then
|
||||
AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Check multiple functions to see whether each needs a declaration.
|
||||
dnl Arrange to define HAVE_DECL_<FUNCTION> to 0 or 1 as appropriate.
|
||||
dnl gcc_AC_CHECK_DECLS(SYMBOLS,
|
||||
dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]])
|
||||
AC_DEFUN([gcc_AC_CHECK_DECLS],
|
||||
[AC_FOREACH([gcc_AC_Func], [$1],
|
||||
[AH_TEMPLATE(AS_TR_CPP(HAVE_DECL_[]gcc_AC_Func),
|
||||
[Define to 1 if we found a declaration for ']gcc_AC_Func[', otherwise
|
||||
define to 0.])])dnl
|
||||
for ac_func in $1
|
||||
do
|
||||
ac_tr_decl=AS_TR_CPP([HAVE_DECL_$ac_func])
|
||||
gcc_AC_CHECK_DECL($ac_func,
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2],
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3],
|
||||
dnl It is possible that the include files passed in here are local headers
|
||||
dnl which supply a backup declaration for the relevant prototype based on
|
||||
dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test
|
||||
dnl will always return success. E.g. see libiberty.h's handling of
|
||||
dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to
|
||||
dnl 1 so that any local headers used do not provide their own prototype
|
||||
dnl during this test.
|
||||
#undef $ac_tr_decl
|
||||
#define $ac_tr_decl 1
|
||||
$4
|
||||
)
|
||||
done
|
||||
])
|
||||
|
||||
dnl 'make compare' can be significantly faster, if cmp itself can
|
||||
dnl skip bytes instead of using tail. The test being performed is
|
||||
dnl "if cmp --ignore-initial=2 t1 t2 && ! cmp --ignore-initial=1 t1 t2"
|
||||
dnl but we need to sink errors and handle broken shells. We also test
|
||||
dnl for the parameter format "cmp file1 file2 skip1 skip2" which is
|
||||
dnl accepted by cmp on some systems.
|
||||
AC_DEFUN([gcc_AC_PROG_CMP_IGNORE_INITIAL],
|
||||
[AC_CACHE_CHECK([for cmp's capabilities], gcc_cv_prog_cmp_skip,
|
||||
[ echo abfoo >t1
|
||||
echo cdfoo >t2
|
||||
gcc_cv_prog_cmp_skip=slowcompare
|
||||
if cmp --ignore-initial=2 t1 t2 > /dev/null 2>&1; then
|
||||
if cmp --ignore-initial=1 t1 t2 > /dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
gcc_cv_prog_cmp_skip=gnucompare
|
||||
fi
|
||||
fi
|
||||
if test $gcc_cv_prog_cmp_skip = slowcompare ; then
|
||||
if cmp t1 t2 2 2 > /dev/null 2>&1; then
|
||||
if cmp t1 t2 1 1 > /dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
gcc_cv_prog_cmp_skip=fastcompare
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm t1 t2
|
||||
])
|
||||
make_compare_target=$gcc_cv_prog_cmp_skip
|
||||
AC_SUBST(make_compare_target)
|
||||
])
|
||||
|
||||
dnl See if symbolic links work and if not, try to substitute either hard links or simple copy.
|
||||
AC_DEFUN([gcc_AC_PROG_LN_S],
|
||||
[AC_MSG_CHECKING(whether ln -s works)
|
||||
AC_CACHE_VAL(gcc_cv_prog_LN_S,
|
||||
[rm -f conftestdata_t
|
||||
echo >conftestdata_f
|
||||
if ln -s conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN_S="ln -s"
|
||||
else
|
||||
if ln conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN_S=ln
|
||||
else
|
||||
if cp -p conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN_S="cp -p"
|
||||
else
|
||||
gcc_cv_prog_LN_S=cp
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm -f conftestdata_f conftestdata_t
|
||||
])dnl
|
||||
LN_S="$gcc_cv_prog_LN_S"
|
||||
if test "$gcc_cv_prog_LN_S" = "ln -s"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
if test "$gcc_cv_prog_LN_S" = "ln"; then
|
||||
AC_MSG_RESULT([no, using ln])
|
||||
else
|
||||
AC_MSG_RESULT([no, and neither does ln, so using $gcc_cv_prog_LN_S])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(LN_S)dnl
|
||||
])
|
||||
|
||||
dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
|
||||
dnl of the usual 2.
|
||||
AC_DEFUN([gcc_AC_FUNC_MKDIR_TAKES_ONE_ARG],
|
||||
[AC_CACHE_CHECK([if mkdir takes one argument], gcc_cv_mkdir_takes_one_arg,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
|
||||
#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, 1, [Define if host mkdir takes a single argument.])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([gcc_AC_PROG_INSTALL],
|
||||
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
# incompatible versions:
|
||||
# SysV /etc/install, /usr/sbin/install
|
||||
# SunOS /usr/etc/install
|
||||
# IRIX /sbin/install
|
||||
# AIX /bin/install
|
||||
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
|
||||
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
|
||||
# ./install, which can be erroneously created by make from ./install.sh.
|
||||
AC_MSG_CHECKING(for a BSD compatible install)
|
||||
if test -z "$INSTALL"; then
|
||||
AC_CACHE_VAL(ac_cv_path_install,
|
||||
[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in $PATH; do
|
||||
# Account for people who put trailing slashes in PATH elements.
|
||||
case "$ac_dir/" in
|
||||
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
|
||||
*)
|
||||
# OSF1 and SCO ODT 3.0 have their own names for install.
|
||||
for ac_prog in ginstall scoinst install; do
|
||||
if test -f $ac_dir/$ac_prog; then
|
||||
if test $ac_prog = install &&
|
||||
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
|
||||
# AIX install. It has an incompatible calling convention.
|
||||
# OSF/1 installbsd also uses dspmsg, but is usable.
|
||||
:
|
||||
else
|
||||
ac_cv_path_install="$ac_dir/$ac_prog -c"
|
||||
break 2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
IFS="$ac_save_IFS"
|
||||
])dnl
|
||||
if test "${ac_cv_path_install+set}" = set; then
|
||||
INSTALL="$ac_cv_path_install"
|
||||
else
|
||||
# As a last resort, use the slow shell script. We don't cache a
|
||||
# path for INSTALL within a source directory, because that will
|
||||
# break other packages using the cache if that directory is
|
||||
# removed, or if the path is relative.
|
||||
INSTALL="$ac_install_sh"
|
||||
fi
|
||||
fi
|
||||
dnl We do special magic for INSTALL instead of AC_SUBST, to get
|
||||
dnl relative paths right.
|
||||
AC_MSG_RESULT($INSTALL)
|
||||
AC_SUBST(INSTALL)dnl
|
||||
|
||||
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
|
||||
# It thinks the first close brace ends the variable substitution.
|
||||
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
|
||||
AC_SUBST(INSTALL_PROGRAM)dnl
|
||||
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
AC_SUBST(INSTALL_DATA)dnl
|
||||
])
|
||||
|
||||
# mmap(2) blacklisting. Some platforms provide the mmap library routine
|
||||
# but don't support all of the features we need from it.
|
||||
AC_DEFUN([gcc_AC_FUNC_MMAP_BLACKLIST],
|
||||
[
|
||||
AC_CHECK_HEADER([sys/mman.h],
|
||||
[gcc_header_sys_mman_h=yes], [gcc_header_sys_mman_h=no])
|
||||
AC_CHECK_FUNC([mmap], [gcc_func_mmap=yes], [gcc_func_mmap=no])
|
||||
if test "$gcc_header_sys_mman_h" != yes \
|
||||
|| test "$gcc_func_mmap" != yes; then
|
||||
gcc_cv_func_mmap_file=no
|
||||
gcc_cv_func_mmap_dev_zero=no
|
||||
gcc_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether read-only mmap of a plain file works],
|
||||
gcc_cv_func_mmap_file,
|
||||
[# Add a system to this blacklist if
|
||||
# mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
|
||||
# memory area containing the same data that you'd get if you applied
|
||||
# read() to the same fd. The only system known to have a problem here
|
||||
# is VMS, where text files have record structure.
|
||||
case "$host_os" in
|
||||
vms* | ultrix*)
|
||||
gcc_cv_func_mmap_file=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_file=yes;;
|
||||
esac])
|
||||
AC_CACHE_CHECK([whether mmap from /dev/zero works],
|
||||
gcc_cv_func_mmap_dev_zero,
|
||||
[# Add a system to this blacklist if it has mmap() but /dev/zero
|
||||
# does not exist, or if mmapping /dev/zero does not give anonymous
|
||||
# zeroed pages with both the following properties:
|
||||
# 1. If you map N consecutive pages in with one call, and then
|
||||
# unmap any subset of those pages, the pages that were not
|
||||
# explicitly unmapped remain accessible.
|
||||
# 2. If you map two adjacent blocks of memory and then unmap them
|
||||
# both at once, they must both go away.
|
||||
# Systems known to be in this category are Windows (all variants),
|
||||
# VMS, and Darwin.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
|
||||
gcc_cv_func_mmap_dev_zero=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_dev_zero=yes;;
|
||||
esac])
|
||||
|
||||
# Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
|
||||
AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon,
|
||||
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
],
|
||||
[int n = MAP_ANONYMOUS;])],
|
||||
gcc_cv_decl_map_anon=yes,
|
||||
gcc_cv_decl_map_anon=no)])
|
||||
|
||||
if test $gcc_cv_decl_map_anon = no; then
|
||||
gcc_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
|
||||
gcc_cv_func_mmap_anon,
|
||||
[# Add a system to this blacklist if it has mmap() and MAP_ANON or
|
||||
# MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
# doesn't give anonymous zeroed pages with the same properties listed
|
||||
# above for use of /dev/zero.
|
||||
# Systems known to be in this category are Windows, VMS, and SCO Unix.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | sco* | udk* )
|
||||
gcc_cv_func_mmap_anon=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_anon=yes;;
|
||||
esac])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $gcc_cv_func_mmap_file = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_FILE, 1,
|
||||
[Define if read-only mmap of a plain file works.])
|
||||
fi
|
||||
if test $gcc_cv_func_mmap_dev_zero = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
|
||||
[Define if mmap of /dev/zero works.])
|
||||
fi
|
||||
if test $gcc_cv_func_mmap_anon = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_ANON, 1,
|
||||
[Define if mmap with MAP_ANON(YMOUS) works.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Locate a program and check that its version is acceptable.
|
||||
dnl AC_PROG_CHECK_VER(var, name, version-switch,
|
||||
dnl version-extract-regexp, version-glob)
|
||||
AC_DEFUN([gcc_AC_CHECK_PROG_VER],
|
||||
[AC_REQUIRE([gcc_AC_BUILD_EXEEXT])
|
||||
AC_CHECK_PROG([$1], [$2], [$2])
|
||||
if test -n "[$]$1"; then
|
||||
# Found it, now check the version.
|
||||
AC_CACHE_CHECK(for modern $2, gcc_cv_prog_$2_modern,
|
||||
[changequote(<<,>>)dnl
|
||||
ac_prog_version=`<<$>>$1 $3 2>&1 |
|
||||
sed -n 's/^.*patsubst(<<$4>>,/,\/).*$/\1/p'`
|
||||
changequote([,])dnl
|
||||
echo "configure:__oline__: version of $2 is $ac_prog_version" >&AS_MESSAGE_LOG_FD
|
||||
changequote(<<,>>)dnl
|
||||
case $ac_prog_version in
|
||||
'') gcc_cv_prog_$2_modern=no;;
|
||||
<<$5>>)
|
||||
gcc_cv_prog_$2_modern=yes;;
|
||||
*) gcc_cv_prog_$2_modern=no;;
|
||||
esac
|
||||
changequote([,])dnl
|
||||
])
|
||||
else
|
||||
gcc_cv_prog_$2_modern=no
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Determine if enumerated bitfields are unsigned. ISO C says they can
|
||||
dnl be either signed or unsigned.
|
||||
dnl
|
||||
AC_DEFUN([gcc_AC_C_ENUM_BF_UNSIGNED],
|
||||
[AC_CACHE_CHECK(for unsigned enumerated bitfields, gcc_cv_enum_bf_unsigned,
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([#include <stdlib.h>
|
||||
enum t { BLAH = 128 } ;
|
||||
struct s_t { enum t member : 8; } s ;
|
||||
int main(void)
|
||||
{
|
||||
s.member = BLAH;
|
||||
if (s.member < 0) exit(1);
|
||||
exit(0);
|
||||
|
||||
}])], gcc_cv_enum_bf_unsigned=yes, gcc_cv_enum_bf_unsigned=no, gcc_cv_enum_bf_unsigned=yes)])
|
||||
if test $gcc_cv_enum_bf_unsigned = yes; then
|
||||
AC_DEFINE(ENUM_BITFIELDS_ARE_UNSIGNED, 1,
|
||||
[Define if enumerated bitfields are treated as unsigned values.])
|
||||
fi])
|
||||
|
||||
dnl Probe number of bits in a byte.
|
||||
dnl Note C89 requires CHAR_BIT >= 8.
|
||||
dnl
|
||||
AC_DEFUN([gcc_AC_C_CHAR_BIT],
|
||||
[AC_CACHE_CHECK(for CHAR_BIT, gcc_cv_decl_char_bit,
|
||||
[AC_EGREP_CPP(found,
|
||||
[#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef CHAR_BIT
|
||||
found
|
||||
#endif], gcc_cv_decl_char_bit=yes, gcc_cv_decl_char_bit=no)
|
||||
])
|
||||
if test $gcc_cv_decl_char_bit = no; then
|
||||
AC_CACHE_CHECK(number of bits in a byte, gcc_cv_c_nbby,
|
||||
[i=8
|
||||
gcc_cv_c_nbby=
|
||||
while test $i -lt 65; do
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,
|
||||
[switch(0) {
|
||||
case (unsigned char)((unsigned long)1 << $i) == ((unsigned long)1 << $i):
|
||||
case (unsigned char)((unsigned long)1<<($i-1)) == ((unsigned long)1<<($i-1)):
|
||||
; }])],
|
||||
[gcc_cv_c_nbby=$i; break])
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed
|
||||
])
|
||||
if test $gcc_cv_c_nbby = failed; then
|
||||
AC_MSG_ERROR(cannot determine number of bits in a byte)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(CHAR_BIT, $gcc_cv_c_nbby,
|
||||
[Define as the number of bits in a byte, if \`limits.h' doesn't.])
|
||||
fi
|
||||
fi])
|
||||
|
||||
AC_DEFUN([gcc_AC_INITFINI_ARRAY],
|
||||
[AC_ARG_ENABLE(initfini-array,
|
||||
[ --enable-initfini-array use .init_array/.fini_array sections],
|
||||
[], [
|
||||
AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
|
||||
gcc_cv_initfini_array, [dnl
|
||||
AC_RUN_IFELSE([AC_LANG_SOURCE([
|
||||
static int x = -1;
|
||||
int main (void) { return x; }
|
||||
int foo (void) { x = 0; }
|
||||
int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;])],
|
||||
[gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no],
|
||||
[gcc_cv_initfini_array=no])])
|
||||
enable_initfini_array=$gcc_cv_initfini_array
|
||||
])
|
||||
if test $enable_initfini_array = yes; then
|
||||
AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
|
||||
[Define .init_array/.fini_array sections are available and working.])
|
||||
fi])
|
||||
|
||||
dnl # _gcc_COMPUTE_GAS_VERSION
|
||||
dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
|
||||
dnl #
|
||||
dnl # WARNING:
|
||||
dnl # gcc_cv_as_gas_srcdir must be defined before this.
|
||||
dnl # This gross requirement will go away eventually.
|
||||
AC_DEFUN([_gcc_COMPUTE_GAS_VERSION],
|
||||
[gcc_cv_as_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
|
||||
for f in $gcc_cv_as_bfd_srcdir/configure \
|
||||
$gcc_cv_as_gas_srcdir/configure \
|
||||
$gcc_cv_as_gas_srcdir/configure.in \
|
||||
$gcc_cv_as_gas_srcdir/Makefile.in ; do
|
||||
gcc_cv_gas_version=`sed -n -e 's/^[[ ]]*\(VERSION=[[0-9]]*\.[[0-9]]*.*\)/\1/p' < $f`
|
||||
if test x$gcc_cv_gas_version != x; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([[0-9]]*\)"`
|
||||
gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[[0-9]]*\.\([[0-9]]*\)"`
|
||||
gcc_cv_gas_patch_version=`expr "$gcc_cv_gas_version" : "VERSION=[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)"`
|
||||
case $gcc_cv_gas_patch_version in
|
||||
"") gcc_cv_gas_patch_version="0" ;;
|
||||
esac
|
||||
gcc_cv_gas_vers=`expr \( \( $gcc_cv_gas_major_version \* 1000 \) \
|
||||
+ $gcc_cv_gas_minor_version \) \* 1000 \
|
||||
+ $gcc_cv_gas_patch_version`
|
||||
]) []dnl # _gcc_COMPUTE_GAS_VERSION
|
||||
|
||||
dnl # gcc_GAS_VERSION_GTE_IFELSE([elf,] major, minor, patchlevel,
|
||||
dnl # [command_if_true = :], [command_if_false = :])
|
||||
dnl # Check to see if the version of GAS is greater than or
|
||||
dnl # equal to the specified version.
|
||||
dnl #
|
||||
dnl # The first ifelse() shortens the shell code if the patchlevel
|
||||
dnl # is unimportant (the usual case). The others handle missing
|
||||
dnl # commands. Note that the tests are structured so that the most
|
||||
dnl # common version number cases are tested first.
|
||||
AC_DEFUN([_gcc_GAS_VERSION_GTE_IFELSE],
|
||||
[ifelse([$1], elf,
|
||||
[if test $in_tree_gas_is_elf = yes \
|
||||
&&],
|
||||
[if]) test $gcc_cv_gas_vers -ge `expr \( \( $2 \* 1000 \) + $3 \) \* 1000 + $4`
|
||||
then dnl
|
||||
ifelse([$5],,:,[$5])[]dnl
|
||||
ifelse([$6],,,[
|
||||
else $6])
|
||||
fi])
|
||||
|
||||
AC_DEFUN([gcc_GAS_VERSION_GTE_IFELSE],
|
||||
[AC_REQUIRE([_gcc_COMPUTE_GAS_VERSION])dnl
|
||||
ifelse([$1], elf, [_gcc_GAS_VERSION_GTE_IFELSE($@)],
|
||||
[_gcc_GAS_VERSION_GTE_IFELSE(,$@)])])
|
||||
|
||||
dnl gcc_GAS_CHECK_FEATURE(description, cv, [[elf,]major,minor,patchlevel],
|
||||
dnl [extra switches to as], [assembler input],
|
||||
dnl [extra testing logic], [command if feature available])
|
||||
dnl
|
||||
dnl Checks for an assembler feature. If we are building an in-tree
|
||||
dnl gas, the feature is available if the associated assembler version
|
||||
dnl is greater than or equal to major.minor.patchlevel. If not, then
|
||||
dnl ASSEMBLER INPUT is fed to the assembler and the feature is available
|
||||
dnl if assembly succeeds. If EXTRA TESTING LOGIC is not the empty string,
|
||||
dnl then it is run instead of simply setting CV to "yes" - it is responsible
|
||||
dnl for doing so, if appropriate.
|
||||
AC_DEFUN([gcc_GAS_CHECK_FEATURE],
|
||||
[AC_CACHE_CHECK([assembler for $1], [$2],
|
||||
[[$2]=no
|
||||
ifelse([$3],,,[dnl
|
||||
if test $in_tree_gas = yes; then
|
||||
gcc_GAS_VERSION_GTE_IFELSE($3, [[$2]=yes])
|
||||
el])if test x$gcc_cv_as != x; then
|
||||
echo ifelse(m4_substr([$5],0,1),[$], "[$5]", '[$5]') > conftest.s
|
||||
if AC_TRY_COMMAND([$gcc_cv_as $4 -o conftest.o conftest.s >&AS_MESSAGE_LOG_FD])
|
||||
then
|
||||
ifelse([$6],, [$2]=yes, [$6])
|
||||
else
|
||||
echo "configure: failed program was" >&AS_MESSAGE_LOG_FD
|
||||
cat conftest.s >&AS_MESSAGE_LOG_FD
|
||||
fi
|
||||
rm -f conftest.o conftest.s
|
||||
fi])
|
||||
ifelse([$7],,,[dnl
|
||||
if test $[$2] = yes; then
|
||||
$7
|
||||
fi])])
|
||||
|
||||
dnl GCC_TARGET_TEMPLATE(KEY)
|
||||
dnl ------------------------
|
||||
dnl Define KEY as a valid configure key on the target machine.
|
||||
|
||||
m4_define([GCC_TARGET_TEMPLATE],
|
||||
[m4_define([GCC_TARGET_TEMPLATE($1)],[])])
|
||||
|
||||
dnl AH_TEMPLATE(KEY, DESCRIPTION)
|
||||
dnl -----------------------------
|
||||
dnl Issue an autoheader template for KEY, i.e., a comment composed of
|
||||
dnl DESCRIPTION (properly wrapped), and then #undef KEY. Redefinition
|
||||
dnl of the macro in autoheader.m4, to support definition of only a few
|
||||
dnl keys while compiling target libraries.
|
||||
|
||||
m4_define([AH_TEMPLATE],
|
||||
[AH_VERBATIM([$1],m4_text_wrap([$2 */], [ ], [/* ])
|
||||
m4_ifdef([GCC_TARGET_TEMPLATE($1)],[],[#ifndef USED_FOR_TARGET
|
||||
])[#undef $1]m4_ifdef([GCC_TARGET_TEMPLATE($1)],[],[
|
||||
#endif
|
||||
]))])
|
||||
|
||||
dnl Make sure that build_exeext is looked for
|
||||
AC_DEFUN([gcc_AC_BUILD_EXEEXT], [
|
||||
ac_executable_extensions="$build_exeext"])
|
||||
|
880
contrib/gcc/aclocal.m4
vendored
880
contrib/gcc/aclocal.m4
vendored
@ -1,784 +1,104 @@
|
||||
sinclude(../config/acx.m4)
|
||||
sinclude(../config/accross.m4)
|
||||
sinclude(../config/gettext.m4)
|
||||
sinclude(../config/progtest.m4)
|
||||
# generated automatically by aclocal 1.9.6 -*- Autoconf -*-
|
||||
|
||||
dnl See if stdbool.h properly defines bool and true/false.
|
||||
AC_DEFUN([gcc_AC_HEADER_STDBOOL],
|
||||
[AC_CACHE_CHECK([for working stdbool.h],
|
||||
ac_cv_header_stdbool_h,
|
||||
[AC_TRY_COMPILE([#include <stdbool.h>],
|
||||
[bool foo = false;],
|
||||
ac_cv_header_stdbool_h=yes, ac_cv_header_stdbool_h=no)])
|
||||
if test $ac_cv_header_stdbool_h = yes; then
|
||||
AC_DEFINE(HAVE_STDBOOL_H, 1,
|
||||
[Define if you have a working <stdbool.h> header file.])
|
||||
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
# 2005 Free Software Foundation, Inc.
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
|
||||
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
# PARTICULAR PURPOSE.
|
||||
|
||||
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
|
||||
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
|
||||
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
|
||||
#
|
||||
# Of course, Automake must honor this variable whenever it calls a
|
||||
# tool from the auxiliary directory. The problem is that $srcdir (and
|
||||
# therefore $ac_aux_dir as well) can be either absolute or relative,
|
||||
# depending on how configure is run. This is pretty annoying, since
|
||||
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
|
||||
# source directory, any form will work fine, but in subdirectories a
|
||||
# relative path needs to be adjusted first.
|
||||
#
|
||||
# $ac_aux_dir/missing
|
||||
# fails when called from a subdirectory if $ac_aux_dir is relative
|
||||
# $top_srcdir/$ac_aux_dir/missing
|
||||
# fails if $ac_aux_dir is absolute,
|
||||
# fails when called from a subdirectory in a VPATH build with
|
||||
# a relative $ac_aux_dir
|
||||
#
|
||||
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
|
||||
# are both prefixed by $srcdir. In an in-source build this is usually
|
||||
# harmless because $srcdir is `.', but things will broke when you
|
||||
# start a VPATH build or use an absolute $srcdir.
|
||||
#
|
||||
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
|
||||
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
|
||||
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
|
||||
# and then we would define $MISSING as
|
||||
# MISSING="\${SHELL} $am_aux_dir/missing"
|
||||
# This will work as long as MISSING is not called from configure, because
|
||||
# unfortunately $(top_srcdir) has no meaning in configure.
|
||||
# However there are other variables, like CC, which are often used in
|
||||
# configure, and could therefore not use this "fixed" $ac_aux_dir.
|
||||
#
|
||||
# Another solution, used here, is to always expand $ac_aux_dir to an
|
||||
# absolute PATH. The drawback is that using absolute paths prevent a
|
||||
# configured tree to be moved without reconfiguration.
|
||||
|
||||
AC_DEFUN([AM_AUX_DIR_EXPAND],
|
||||
[dnl Rely on autoconf to set up CDPATH properly.
|
||||
AC_PREREQ([2.50])dnl
|
||||
# expand $ac_aux_dir to an absolute path
|
||||
am_aux_dir=`cd $ac_aux_dir && pwd`
|
||||
])
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 3
|
||||
|
||||
# AM_PROG_CC_C_O
|
||||
# --------------
|
||||
# Like AC_PROG_CC_C_O, but changed for automake.
|
||||
AC_DEFUN([AM_PROG_CC_C_O],
|
||||
[AC_REQUIRE([AC_PROG_CC_C_O])dnl
|
||||
AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
# FIXME: we rely on the cache variable name because
|
||||
# there is no other way.
|
||||
set dummy $CC
|
||||
ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
|
||||
if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then
|
||||
# Losing compiler, so override with the script.
|
||||
# FIXME: It is wrong to rewrite CC.
|
||||
# But if we don't then we get into trouble of one sort or another.
|
||||
# A longer-term fix would be to have automake use am__CC in this case,
|
||||
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
|
||||
CC="$am_aux_dir/compile $CC"
|
||||
fi
|
||||
])
|
||||
|
||||
dnl See whether we can include both string.h and strings.h.
|
||||
AC_DEFUN([gcc_AC_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, 1, [Define if you can safely include both <string.h> and <strings.h>.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl See whether we need a declaration for a function.
|
||||
dnl The result is highly dependent on the INCLUDES passed in, so make sure
|
||||
dnl to use a different cache variable name in this macro if it is invoked
|
||||
dnl in a different context somewhere else.
|
||||
dnl gcc_AC_CHECK_DECL(SYMBOL,
|
||||
dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, INCLUDES]]])
|
||||
AC_DEFUN([gcc_AC_CHECK_DECL],
|
||||
[AC_MSG_CHECKING([whether $1 is declared])
|
||||
AC_CACHE_VAL(gcc_cv_have_decl_$1,
|
||||
[AC_TRY_COMPILE([$4],
|
||||
[#ifndef $1
|
||||
char *(*pfn) = (char *(*)) $1 ;
|
||||
#endif], eval "gcc_cv_have_decl_$1=yes", eval "gcc_cv_have_decl_$1=no")])
|
||||
if eval "test \"`echo '$gcc_cv_have_decl_'$1`\" = yes"; then
|
||||
AC_MSG_RESULT(yes) ; ifelse([$2], , :, [$2])
|
||||
else
|
||||
AC_MSG_RESULT(no) ; ifelse([$3], , :, [$3])
|
||||
fi
|
||||
])dnl
|
||||
|
||||
dnl Check multiple functions to see whether each needs a declaration.
|
||||
dnl Arrange to define HAVE_DECL_<FUNCTION> to 0 or 1 as appropriate.
|
||||
dnl gcc_AC_CHECK_DECLS(SYMBOLS,
|
||||
dnl [ACTION-IF-NEEDED [, ACTION-IF-NOT-NEEDED [, INCLUDES]]])
|
||||
AC_DEFUN([gcc_AC_CHECK_DECLS],
|
||||
[for ac_func in $1
|
||||
do
|
||||
changequote(, )dnl
|
||||
ac_tr_decl=HAVE_DECL_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
|
||||
changequote([, ])dnl
|
||||
gcc_AC_CHECK_DECL($ac_func,
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 1) $2],
|
||||
[AC_DEFINE_UNQUOTED($ac_tr_decl, 0) $3],
|
||||
dnl It is possible that the include files passed in here are local headers
|
||||
dnl which supply a backup declaration for the relevant prototype based on
|
||||
dnl the definition of (or lack of) the HAVE_DECL_ macro. If so, this test
|
||||
dnl will always return success. E.g. see libiberty.h's handling of
|
||||
dnl `basename'. To avoid this, we define the relevant HAVE_DECL_ macro to
|
||||
dnl 1 so that any local headers used do not provide their own prototype
|
||||
dnl during this test.
|
||||
#undef $ac_tr_decl
|
||||
#define $ac_tr_decl 1
|
||||
$4
|
||||
)
|
||||
done
|
||||
dnl Automatically generate config.h entries via autoheader.
|
||||
if test x = y ; then
|
||||
patsubst(translit([$1], [a-z], [A-Z]), [\w+],
|
||||
[AC_DEFINE([HAVE_DECL_\&], 1,
|
||||
[Define to 1 if we found this declaration otherwise define to 0.])])dnl
|
||||
fi
|
||||
])
|
||||
|
||||
dnl 'make compare' can be significantly faster, if cmp itself can
|
||||
dnl skip bytes instead of using tail. The test being performed is
|
||||
dnl "if cmp --ignore-initial=2 t1 t2 && ! cmp --ignore-initial=1 t1 t2"
|
||||
dnl but we need to sink errors and handle broken shells. We also test
|
||||
dnl for the parameter format "cmp file1 file2 skip1 skip2" which is
|
||||
dnl accepted by cmp on some systems.
|
||||
AC_DEFUN([gcc_AC_PROG_CMP_IGNORE_INITIAL],
|
||||
[AC_CACHE_CHECK([for cmp's capabilities], gcc_cv_prog_cmp_skip,
|
||||
[ echo abfoo >t1
|
||||
echo cdfoo >t2
|
||||
gcc_cv_prog_cmp_skip=slowcompare
|
||||
if cmp --ignore-initial=2 t1 t2 > /dev/null 2>&1; then
|
||||
if cmp --ignore-initial=1 t1 t2 > /dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
gcc_cv_prog_cmp_skip=gnucompare
|
||||
fi
|
||||
fi
|
||||
if test $gcc_cv_prog_cmp_skip = slowcompare ; then
|
||||
if cmp t1 t2 2 2 > /dev/null 2>&1; then
|
||||
if cmp t1 t2 1 1 > /dev/null 2>&1; then
|
||||
:
|
||||
else
|
||||
gcc_cv_prog_cmp_skip=fastcompare
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm t1 t2
|
||||
])
|
||||
make_compare_target=$gcc_cv_prog_cmp_skip
|
||||
AC_SUBST(make_compare_target)
|
||||
])
|
||||
|
||||
dnl See if the printf functions in libc support %p in format strings.
|
||||
AC_DEFUN([gcc_AC_FUNC_PRINTF_PTR],
|
||||
[AC_CACHE_CHECK(whether the printf functions support %p,
|
||||
gcc_cv_func_printf_ptr,
|
||||
[AC_TRY_RUN([#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
char buf[64];
|
||||
char *p = buf, *q = NULL;
|
||||
sprintf(buf, "%p", p);
|
||||
sscanf(buf, "%p", &q);
|
||||
return (p != q);
|
||||
}], gcc_cv_func_printf_ptr=yes, gcc_cv_func_printf_ptr=no,
|
||||
gcc_cv_func_printf_ptr=no)
|
||||
rm -f core core.* *.core])
|
||||
if test $gcc_cv_func_printf_ptr = yes ; then
|
||||
AC_DEFINE(HAVE_PRINTF_PTR, 1, [Define if printf supports "%p".])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl See if symbolic links work and if not, try to substitute either hard links or simple copy.
|
||||
AC_DEFUN([gcc_AC_PROG_LN_S],
|
||||
[AC_MSG_CHECKING(whether ln -s works)
|
||||
AC_CACHE_VAL(gcc_cv_prog_LN_S,
|
||||
[rm -f conftestdata_t
|
||||
echo >conftestdata_f
|
||||
if ln -s conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN_S="ln -s"
|
||||
else
|
||||
if ln conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN_S=ln
|
||||
else
|
||||
gcc_cv_prog_LN_S=cp
|
||||
fi
|
||||
fi
|
||||
rm -f conftestdata_f conftestdata_t
|
||||
])dnl
|
||||
LN_S="$gcc_cv_prog_LN_S"
|
||||
if test "$gcc_cv_prog_LN_S" = "ln -s"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
if test "$gcc_cv_prog_LN_S" = "ln"; then
|
||||
AC_MSG_RESULT([no, using ln])
|
||||
else
|
||||
AC_MSG_RESULT([no, and neither does ln, so using cp])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(LN_S)dnl
|
||||
])
|
||||
|
||||
dnl See if hard links work and if not, try to substitute either symbolic links or simple copy.
|
||||
AC_DEFUN([gcc_AC_PROG_LN],
|
||||
[AC_MSG_CHECKING(whether ln works)
|
||||
AC_CACHE_VAL(gcc_cv_prog_LN,
|
||||
[rm -f conftestdata_t
|
||||
echo >conftestdata_f
|
||||
if ln conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN="ln"
|
||||
else
|
||||
if ln -s conftestdata_f conftestdata_t 2>/dev/null
|
||||
then
|
||||
gcc_cv_prog_LN="ln -s"
|
||||
else
|
||||
gcc_cv_prog_LN=cp
|
||||
fi
|
||||
fi
|
||||
rm -f conftestdata_f conftestdata_t
|
||||
])dnl
|
||||
LN="$gcc_cv_prog_LN"
|
||||
if test "$gcc_cv_prog_LN" = "ln"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
else
|
||||
if test "$gcc_cv_prog_LN" = "ln -s"; then
|
||||
AC_MSG_RESULT([no, using ln -s])
|
||||
else
|
||||
AC_MSG_RESULT([no, and neither does ln -s, so using cp])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(LN)dnl
|
||||
])
|
||||
|
||||
dnl Check whether _Bool is built-in.
|
||||
AC_DEFUN([gcc_AC_C__BOOL],
|
||||
[AC_CACHE_CHECK(for built-in _Bool, gcc_cv_c__bool,
|
||||
[AC_TRY_COMPILE(,
|
||||
[_Bool foo;],
|
||||
gcc_cv_c__bool=yes, gcc_cv_c__bool=no)
|
||||
])
|
||||
if test $gcc_cv_c__bool = yes; then
|
||||
AC_DEFINE(HAVE__BOOL, 1, [Define if the \`_Bool' type is built-in.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Define MKDIR_TAKES_ONE_ARG if mkdir accepts only one argument instead
|
||||
dnl of the usual 2.
|
||||
AC_DEFUN([gcc_AC_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, 1, [Define if host mkdir takes a single argument.])
|
||||
fi
|
||||
])
|
||||
|
||||
AC_DEFUN([gcc_AC_PROG_INSTALL],
|
||||
[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
# incompatible versions:
|
||||
# SysV /etc/install, /usr/sbin/install
|
||||
# SunOS /usr/etc/install
|
||||
# IRIX /sbin/install
|
||||
# AIX /bin/install
|
||||
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
|
||||
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
|
||||
# ./install, which can be erroneously created by make from ./install.sh.
|
||||
AC_MSG_CHECKING(for a BSD compatible install)
|
||||
if test -z "$INSTALL"; then
|
||||
AC_CACHE_VAL(ac_cv_path_install,
|
||||
[ IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
|
||||
for ac_dir in $PATH; do
|
||||
# Account for people who put trailing slashes in PATH elements.
|
||||
case "$ac_dir/" in
|
||||
/|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
|
||||
*)
|
||||
# OSF1 and SCO ODT 3.0 have their own names for install.
|
||||
for ac_prog in ginstall scoinst install; do
|
||||
if test -f $ac_dir/$ac_prog; then
|
||||
if test $ac_prog = install &&
|
||||
grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
|
||||
# AIX install. It has an incompatible calling convention.
|
||||
# OSF/1 installbsd also uses dspmsg, but is usable.
|
||||
:
|
||||
else
|
||||
ac_cv_path_install="$ac_dir/$ac_prog -c"
|
||||
break 2
|
||||
fi
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
IFS="$ac_save_IFS"
|
||||
])dnl
|
||||
if test "${ac_cv_path_install+set}" = set; then
|
||||
INSTALL="$ac_cv_path_install"
|
||||
else
|
||||
# As a last resort, use the slow shell script. We don't cache a
|
||||
# path for INSTALL within a source directory, because that will
|
||||
# break other packages using the cache if that directory is
|
||||
# removed, or if the path is relative.
|
||||
INSTALL="$ac_install_sh"
|
||||
fi
|
||||
fi
|
||||
dnl We do special magic for INSTALL instead of AC_SUBST, to get
|
||||
dnl relative paths right.
|
||||
AC_MSG_RESULT($INSTALL)
|
||||
AC_SUBST(INSTALL)dnl
|
||||
|
||||
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
|
||||
# It thinks the first close brace ends the variable substitution.
|
||||
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
|
||||
AC_SUBST(INSTALL_PROGRAM)dnl
|
||||
|
||||
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
|
||||
AC_SUBST(INSTALL_DATA)dnl
|
||||
])
|
||||
|
||||
dnl Test for GNAT.
|
||||
dnl We require the gnatbind program, and a compiler driver that
|
||||
dnl understands Ada. We use the user's CC setting, already found.
|
||||
dnl
|
||||
dnl Sets the shell variable have_gnat to yes or no as appropriate, and
|
||||
dnl substitutes GNATBIND.
|
||||
AC_DEFUN([gcc_AC_PROG_GNAT],
|
||||
[AC_REQUIRE([AC_CHECK_TOOL_PREFIX])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_CHECK_TOOL(GNATBIND, gnatbind, no)
|
||||
AC_CACHE_CHECK([whether compiler driver understands Ada],
|
||||
gcc_cv_cc_supports_ada,
|
||||
[cat >conftest.adb <<EOF
|
||||
procedure conftest is begin null; end conftest;
|
||||
EOF
|
||||
gcc_cv_cc_supports_ada=no
|
||||
# There is a bug in old released versions of GCC which causes the
|
||||
# driver to exit successfully when the appropriate language module
|
||||
# has not been installed. This is fixed in 2.95.4, 3.0.2, and 3.1.
|
||||
# Therefore we must check for the error message as well as an
|
||||
# unsuccessful exit.
|
||||
# Other compilers, like HP Tru64 UNIX cc, exit successfully when
|
||||
# given a .adb file, but produce no object file. So we must check
|
||||
# if an object file was really produced to guard against this.
|
||||
errors=`(${CC} -c conftest.adb) 2>&1 || echo failure`
|
||||
if test x"$errors" = x && test -f conftest.$ac_objext; then
|
||||
gcc_cv_cc_supports_ada=yes
|
||||
break
|
||||
fi
|
||||
rm -f conftest.*])
|
||||
|
||||
if test x$GNATBIND != xno && test x$gcc_cv_cc_supports_ada != xno; then
|
||||
have_gnat=yes
|
||||
else
|
||||
have_gnat=no
|
||||
fi
|
||||
])
|
||||
|
||||
dnl GCC_PATH_PROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]])
|
||||
dnl like AC_PATH_PROG but use other cache variables
|
||||
AC_DEFUN([GCC_PATH_PROG],
|
||||
[# 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(gcc_cv_path_$1,
|
||||
[case "[$]$1" in
|
||||
/*)
|
||||
gcc_cv_path_$1="[$]$1" # Let the user override the test with a path.
|
||||
;;
|
||||
?:/*)
|
||||
gcc_cv_path_$1="[$]$1" # Let the user override the test with a dos path.
|
||||
;;
|
||||
*)
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
|
||||
dnl $ac_dummy forces splitting on constant user-supplied paths.
|
||||
dnl POSIX.2 word splitting is done only on the output of word expansions,
|
||||
dnl not every word. This closes a longstanding sh security hole.
|
||||
ac_dummy="ifelse([$4], , $PATH, [$4])"
|
||||
for ac_dir in $ac_dummy; do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f $ac_dir/$ac_word; then
|
||||
gcc_cv_path_$1="$ac_dir/$ac_word"
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
dnl If no 3rd arg is given, leave the cache variable unset,
|
||||
dnl so GCC_PATH_PROGS will keep looking.
|
||||
ifelse([$3], , , [ test -z "[$]gcc_cv_path_$1" && gcc_cv_path_$1="$3"
|
||||
])dnl
|
||||
;;
|
||||
esac])dnl
|
||||
$1="$gcc_cv_path_$1"
|
||||
if test -n "[$]$1"; then
|
||||
AC_MSG_RESULT([$]$1)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
AC_SUBST($1)dnl
|
||||
])
|
||||
|
||||
# mmap(2) blacklisting. Some platforms provide the mmap library routine
|
||||
# but don't support all of the features we need from it.
|
||||
AC_DEFUN([gcc_AC_FUNC_MMAP_BLACKLIST],
|
||||
[if test $ac_cv_header_sys_mman_h != yes \
|
||||
|| test $ac_cv_func_mmap != yes; then
|
||||
gcc_cv_func_mmap_file=no
|
||||
gcc_cv_func_mmap_dev_zero=no
|
||||
gcc_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether read-only mmap of a plain file works],
|
||||
gcc_cv_func_mmap_file,
|
||||
[# Add a system to this blacklist if
|
||||
# mmap(0, stat_size, PROT_READ, MAP_PRIVATE, fd, 0) doesn't return a
|
||||
# memory area containing the same data that you'd get if you applied
|
||||
# read() to the same fd. The only system known to have a problem here
|
||||
# is VMS, where text files have record structure.
|
||||
case "$host_os" in
|
||||
vms* | ultrix*)
|
||||
gcc_cv_func_mmap_file=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_file=yes;;
|
||||
esac])
|
||||
AC_CACHE_CHECK([whether mmap from /dev/zero works],
|
||||
gcc_cv_func_mmap_dev_zero,
|
||||
[# Add a system to this blacklist if it has mmap() but /dev/zero
|
||||
# does not exist, or if mmapping /dev/zero does not give anonymous
|
||||
# zeroed pages with both the following properties:
|
||||
# 1. If you map N consecutive pages in with one call, and then
|
||||
# unmap any subset of those pages, the pages that were not
|
||||
# explicitly unmapped remain accessible.
|
||||
# 2. If you map two adjacent blocks of memory and then unmap them
|
||||
# both at once, they must both go away.
|
||||
# Systems known to be in this category are Windows (all variants),
|
||||
# VMS, and Darwin.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | darwin* | ultrix* | hpux10* | hpux11.00)
|
||||
gcc_cv_func_mmap_dev_zero=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_dev_zero=yes;;
|
||||
esac])
|
||||
|
||||
# Unlike /dev/zero, the MAP_ANON(YMOUS) defines can be probed for.
|
||||
AC_CACHE_CHECK([for MAP_ANON(YMOUS)], gcc_cv_decl_map_anon,
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
],
|
||||
[int n = MAP_ANONYMOUS;],
|
||||
gcc_cv_decl_map_anon=yes,
|
||||
gcc_cv_decl_map_anon=no)])
|
||||
|
||||
if test $gcc_cv_decl_map_anon = no; then
|
||||
gcc_cv_func_mmap_anon=no
|
||||
else
|
||||
AC_CACHE_CHECK([whether mmap with MAP_ANON(YMOUS) works],
|
||||
gcc_cv_func_mmap_anon,
|
||||
[# Add a system to this blacklist if it has mmap() and MAP_ANON or
|
||||
# MAP_ANONYMOUS, but using mmap(..., MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
|
||||
# doesn't give anonymous zeroed pages with the same properties listed
|
||||
# above for use of /dev/zero.
|
||||
# Systems known to be in this category are Windows, VMS, and SCO Unix.
|
||||
case "$host_os" in
|
||||
vms* | cygwin* | pe | mingw* | sco* | udk* )
|
||||
gcc_cv_func_mmap_anon=no ;;
|
||||
*)
|
||||
gcc_cv_func_mmap_anon=yes;;
|
||||
esac])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $gcc_cv_func_mmap_file = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_FILE, 1,
|
||||
[Define if read-only mmap of a plain file works.])
|
||||
fi
|
||||
if test $gcc_cv_func_mmap_dev_zero = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_DEV_ZERO, 1,
|
||||
[Define if mmap of /dev/zero works.])
|
||||
fi
|
||||
if test $gcc_cv_func_mmap_anon = yes; then
|
||||
AC_DEFINE(HAVE_MMAP_ANON, 1,
|
||||
[Define if mmap with MAP_ANON(YMOUS) works.])
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Locate a program and check that its version is acceptable.
|
||||
dnl AC_PROG_CHECK_VER(var, name, version-switch,
|
||||
dnl version-extract-regexp, version-glob)
|
||||
AC_DEFUN([gcc_AC_CHECK_PROG_VER],
|
||||
[AC_CHECK_PROG([$1], [$2], [$2])
|
||||
if test -n "[$]$1"; then
|
||||
# Found it, now check the version.
|
||||
AC_CACHE_CHECK(for modern $2, gcc_cv_prog_$2_modern,
|
||||
[changequote(<<,>>)dnl
|
||||
ac_prog_version=`<<$>>$1 $3 2>&1 |
|
||||
sed -n 's/^.*patsubst(<<$4>>,/,\/).*$/\1/p'`
|
||||
changequote([,])dnl
|
||||
echo "configure:__oline__: version of $2 is $ac_prog_version" >&AC_FD_CC
|
||||
changequote(<<,>>)dnl
|
||||
case $ac_prog_version in
|
||||
'') gcc_cv_prog_$2_modern=no;;
|
||||
<<$5>>)
|
||||
gcc_cv_prog_$2_modern=yes;;
|
||||
*) gcc_cv_prog_$2_modern=no;;
|
||||
esac
|
||||
changequote([,])dnl
|
||||
])
|
||||
else
|
||||
gcc_cv_prog_$2_modern=no
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Determine if enumerated bitfields are unsigned. ISO C says they can
|
||||
dnl be either signed or unsigned.
|
||||
dnl
|
||||
AC_DEFUN([gcc_AC_C_ENUM_BF_UNSIGNED],
|
||||
[AC_CACHE_CHECK(for unsigned enumerated bitfields, gcc_cv_enum_bf_unsigned,
|
||||
[AC_TRY_RUN(#include <stdlib.h>
|
||||
enum t { BLAH = 128 } ;
|
||||
struct s_t { enum t member : 8; } s ;
|
||||
int main(void)
|
||||
{
|
||||
s.member = BLAH;
|
||||
if (s.member < 0) exit(1);
|
||||
exit(0);
|
||||
|
||||
}, gcc_cv_enum_bf_unsigned=yes, gcc_cv_enum_bf_unsigned=no, gcc_cv_enum_bf_unsigned=yes)])
|
||||
if test $gcc_cv_enum_bf_unsigned = yes; then
|
||||
AC_DEFINE(ENUM_BITFIELDS_ARE_UNSIGNED, 1,
|
||||
[Define if enumerated bitfields are treated as unsigned values.])
|
||||
fi])
|
||||
|
||||
dnl Probe number of bits in a byte.
|
||||
dnl Note C89 requires CHAR_BIT >= 8.
|
||||
dnl
|
||||
AC_DEFUN([gcc_AC_C_CHAR_BIT],
|
||||
[AC_CACHE_CHECK(for CHAR_BIT, gcc_cv_decl_char_bit,
|
||||
[AC_EGREP_CPP(found,
|
||||
[#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef CHAR_BIT
|
||||
found
|
||||
#endif], gcc_cv_decl_char_bit=yes, gcc_cv_decl_char_bit=no)
|
||||
])
|
||||
if test $gcc_cv_decl_char_bit = no; then
|
||||
AC_CACHE_CHECK(number of bits in a byte, gcc_cv_c_nbby,
|
||||
[i=8
|
||||
gcc_cv_c_nbby=
|
||||
while test $i -lt 65; do
|
||||
AC_TRY_COMPILE(,
|
||||
[switch(0) {
|
||||
case (unsigned char)((unsigned long)1 << $i) == ((unsigned long)1 << $i):
|
||||
case (unsigned char)((unsigned long)1<<($i-1)) == ((unsigned long)1<<($i-1)):
|
||||
; }],
|
||||
[gcc_cv_c_nbby=$i; break])
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
test -z "$gcc_cv_c_nbby" && gcc_cv_c_nbby=failed
|
||||
])
|
||||
if test $gcc_cv_c_nbby = failed; then
|
||||
AC_MSG_ERROR(cannot determine number of bits in a byte)
|
||||
else
|
||||
AC_DEFINE_UNQUOTED(CHAR_BIT, $gcc_cv_c_nbby,
|
||||
[Define as the number of bits in a byte, if \`limits.h' doesn't.])
|
||||
fi
|
||||
fi])
|
||||
|
||||
dnl Checking for long long.
|
||||
dnl By Caolan McNamara <caolan@skynet.ie>
|
||||
dnl Added check for __int64, Zack Weinberg <zackw@stanford.edu>
|
||||
dnl
|
||||
AC_DEFUN([gcc_AC_C_LONG_LONG],
|
||||
[AC_CACHE_CHECK(for long long int, ac_cv_c_long_long,
|
||||
[AC_TRY_COMPILE(,[long long int i;],
|
||||
ac_cv_c_long_long=yes,
|
||||
ac_cv_c_long_long=no)])
|
||||
if test $ac_cv_c_long_long = yes; then
|
||||
AC_DEFINE(HAVE_LONG_LONG, 1,
|
||||
[Define if your compiler supports the \`long long' type.])
|
||||
fi
|
||||
AC_CACHE_CHECK(for __int64, ac_cv_c___int64,
|
||||
[AC_TRY_COMPILE(,[__int64 i;],
|
||||
ac_cv_c___int64=yes,
|
||||
ac_cv_c___int64=no)])
|
||||
if test $ac_cv_c___int64 = yes; then
|
||||
AC_DEFINE(HAVE___INT64, 1,
|
||||
[Define if your compiler supports the \`__int64' type.])
|
||||
fi
|
||||
])
|
||||
|
||||
#serial AM2
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_DEFUN([AM_ICONV],
|
||||
[
|
||||
dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
|
||||
dnl those with the standalone portable GNU libiconv installed).
|
||||
|
||||
am_cv_lib_iconv_ldpath=
|
||||
AC_ARG_WITH([libiconv-prefix],
|
||||
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
|
||||
for dir in `echo "$withval" | tr : ' '`; do
|
||||
if test -d $dir/include; then CPPFLAGS="$CPPFLAGS -I$dir/include"; fi
|
||||
if test -d $dir/lib; then am_cv_lib_iconv_ldpath="-L$dir/lib"; fi
|
||||
done
|
||||
])
|
||||
|
||||
AC_CHECK_HEADERS([iconv.h])
|
||||
|
||||
AC_CACHE_CHECK(for iconv, am_cv_func_iconv, [
|
||||
am_cv_func_iconv="no, consider installing GNU libiconv"
|
||||
am_cv_lib_iconv=no
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_func_iconv=yes)
|
||||
if test "$am_cv_func_iconv" != yes; then
|
||||
am_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $am_cv_libiconv_ldpath -liconv"
|
||||
AC_TRY_LINK([#include <stdlib.h>
|
||||
#include <iconv.h>],
|
||||
[iconv_t cd = iconv_open("","");
|
||||
iconv(cd,NULL,NULL,NULL,NULL);
|
||||
iconv_close(cd);],
|
||||
am_cv_lib_iconv=yes
|
||||
am_cv_func_iconv=yes)
|
||||
LIBS="$am_save_LIBS"
|
||||
fi
|
||||
])
|
||||
if test "$am_cv_func_iconv" = yes; then
|
||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||
AC_MSG_CHECKING([for iconv declaration])
|
||||
AC_CACHE_VAL(am_cv_proto_iconv, [
|
||||
AC_TRY_COMPILE([
|
||||
#include <stdlib.h>
|
||||
#include <iconv.h>
|
||||
extern
|
||||
#ifdef __cplusplus
|
||||
"C"
|
||||
#endif
|
||||
#if defined(__STDC__) || defined(__cplusplus)
|
||||
size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
|
||||
#else
|
||||
size_t iconv();
|
||||
#endif
|
||||
], [], am_cv_proto_iconv_arg1="", am_cv_proto_iconv_arg1="const")
|
||||
am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
|
||||
am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
|
||||
AC_MSG_RESULT([$]{ac_t:-
|
||||
}[$]am_cv_proto_iconv)
|
||||
AC_DEFINE_UNQUOTED(ICONV_CONST, $am_cv_proto_iconv_arg1,
|
||||
[Define as const if the declaration of iconv() needs const.])
|
||||
fi
|
||||
LIBICONV=
|
||||
if test "$am_cv_lib_iconv" = yes; then
|
||||
LIBICONV="$am_cv_lib_iconv_ldpath -liconv"
|
||||
fi
|
||||
AC_SUBST(LIBICONV)
|
||||
])
|
||||
|
||||
AC_DEFUN([gcc_AC_INITFINI_ARRAY],
|
||||
[AC_ARG_ENABLE(initfini-array,
|
||||
[ --enable-initfini-array use .init_array/.fini_array sections],
|
||||
[], [
|
||||
AC_CACHE_CHECK(for .preinit_array/.init_array/.fini_array support,
|
||||
gcc_cv_initfini_array, [dnl
|
||||
AC_TRY_RUN([
|
||||
static int x = -1;
|
||||
int main (void) { return x; }
|
||||
int foo (void) { x = 0; }
|
||||
int (*fp) (void) __attribute__ ((section (".init_array"))) = foo;],
|
||||
[gcc_cv_initfini_array=yes], [gcc_cv_initfini_array=no],
|
||||
[gcc_cv_initfini_array=no])])
|
||||
enable_initfini_array=$gcc_cv_initfini_array
|
||||
])
|
||||
if test $enable_initfini_array = yes; then
|
||||
AC_DEFINE(HAVE_INITFINI_ARRAY, 1,
|
||||
[Define .init_array/.fini_array sections are available and working.])
|
||||
fi])
|
||||
|
||||
dnl # _gcc_COMPUTE_GAS_VERSION
|
||||
dnl # Used by gcc_GAS_VERSION_GTE_IFELSE
|
||||
dnl #
|
||||
dnl # WARNING:
|
||||
dnl # gcc_cv_as_gas_srcdir must be defined before this.
|
||||
dnl # This gross requirement will go away eventually.
|
||||
AC_DEFUN([_gcc_COMPUTE_GAS_VERSION],
|
||||
[gcc_cv_as_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd
|
||||
for f in $gcc_cv_as_bfd_srcdir/configure \
|
||||
$gcc_cv_as_gas_srcdir/configure \
|
||||
$gcc_cv_as_gas_srcdir/configure.in \
|
||||
$gcc_cv_as_gas_srcdir/Makefile.in ; do
|
||||
gcc_cv_gas_version=`grep '^VERSION=[[0-9]]*\.[[0-9]]*' $f`
|
||||
if test x$gcc_cv_gas_version != x; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
gcc_cv_gas_major_version=`expr "$gcc_cv_gas_version" : "VERSION=\([[0-9]]*\)"`
|
||||
gcc_cv_gas_minor_version=`expr "$gcc_cv_gas_version" : "VERSION=[[0-9]]*\.\([[0-9]]*\)"`
|
||||
gcc_cv_gas_patch_version=`expr "$gcc_cv_gas_version" : "VERSION=[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)"`
|
||||
case $gcc_cv_gas_patch_version in
|
||||
"") gcc_cv_gas_patch_version="0" ;;
|
||||
esac
|
||||
gcc_cv_gas_vers=`expr \( \( $gcc_cv_gas_major_version \* 1000 \) \
|
||||
+ $gcc_cv_gas_minor_version \) \* 1000 \
|
||||
+ $gcc_cv_gas_patch_version`
|
||||
]) []dnl # _gcc_COMPUTE_GAS_VERSION
|
||||
|
||||
dnl # gcc_GAS_VERSION_GTE_IFELSE([elf,] major, minor, patchlevel,
|
||||
dnl # [command_if_true = :], [command_if_false = :])
|
||||
dnl # Check to see if the version of GAS is greater than or
|
||||
dnl # equal to the specified version.
|
||||
dnl #
|
||||
dnl # The first ifelse() shortens the shell code if the patchlevel
|
||||
dnl # is unimportant (the usual case). The others handle missing
|
||||
dnl # commands. Note that the tests are structured so that the most
|
||||
dnl # common version number cases are tested first.
|
||||
AC_DEFUN([_gcc_GAS_VERSION_GTE_IFELSE],
|
||||
[ifelse([$1], elf,
|
||||
[if test $in_tree_gas_is_elf = yes \
|
||||
&&],
|
||||
[if]) test $gcc_cv_gas_vers -ge `expr \( \( $2 \* 1000 \) + $3 \) \* 1000 + $4`
|
||||
then dnl
|
||||
ifelse([$5],,:,[$5])[]dnl
|
||||
ifelse([$6],,,[
|
||||
else $6])
|
||||
fi])
|
||||
|
||||
AC_DEFUN([gcc_GAS_VERSION_GTE_IFELSE],
|
||||
[AC_REQUIRE([_gcc_COMPUTE_GAS_VERSION])dnl
|
||||
ifelse([$1], elf, [_gcc_GAS_VERSION_GTE_IFELSE($@)],
|
||||
[_gcc_GAS_VERSION_GTE_IFELSE(,$@)])])
|
||||
|
||||
dnl gcc_GAS_CHECK_FEATURE(description, cv, [[elf,]major,minor,patchlevel],
|
||||
dnl [extra switches to as], [assembler input],
|
||||
dnl [extra testing logic], [command if feature available])
|
||||
dnl
|
||||
dnl Checks for an assembler feature. If we are building an in-tree
|
||||
dnl gas, the feature is available if the associated assembler version
|
||||
dnl is greater than or equal to major.minor.patchlevel. If not, then
|
||||
dnl ASSEMBLER INPUT is fed to the assembler and the feature is available
|
||||
dnl if assembly succeeds. If EXTRA TESTING LOGIC is not the empty string,
|
||||
dnl then it is run instead of simply setting CV to "yes" - it is responsible
|
||||
dnl for doing so, if appropriate.
|
||||
AC_DEFUN([gcc_GAS_CHECK_FEATURE],
|
||||
[AC_CACHE_CHECK([assembler for $1], [$2],
|
||||
[[$2]=no
|
||||
ifelse([$3],,,[dnl
|
||||
if test $in_tree_gas = yes; then
|
||||
gcc_GAS_VERSION_GTE_IFELSE($3, [[$2]=yes])
|
||||
el])if test x$gcc_cv_as != x; then
|
||||
echo ifelse(m4_substr([$5],0,1),[$], "[$5]", '[$5]') > conftest.s
|
||||
if AC_TRY_COMMAND([$gcc_cv_as $4 -o conftest.o conftest.s >&AC_FD_CC])
|
||||
then
|
||||
ifelse([$6],, [$2]=yes, [$6])
|
||||
else
|
||||
echo "configure: failed program was" >&AC_FD_CC
|
||||
cat conftest.s >&AC_FD_CC
|
||||
fi
|
||||
rm -f conftest.o conftest.s
|
||||
fi])
|
||||
ifelse([$7],,,[dnl
|
||||
if test $[$2] = yes; then
|
||||
$7
|
||||
fi])])
|
||||
|
||||
# lcmessage.m4 serial 3 (gettext-0.11.3)
|
||||
dnl Copyright (C) 1995-2002 Free Software Foundation, Inc.
|
||||
dnl This file is free software, distributed under the terms of the GNU
|
||||
dnl General Public License. As a special exception to the GNU General
|
||||
dnl Public License, this file may be distributed as part of a program
|
||||
dnl that contains a configuration script generated by Autoconf, under
|
||||
dnl the same distribution terms as the rest of that program.
|
||||
dnl
|
||||
dnl This file can can be used in projects which are not available under
|
||||
dnl the GNU General Public License or the GNU Library General Public
|
||||
dnl License but which still want to provide support for the GNU gettext
|
||||
dnl functionality.
|
||||
dnl Please note that the actual code of the GNU gettext library is covered
|
||||
dnl by the GNU Library General Public License, and the rest of the GNU
|
||||
dnl gettext package package is covered by the GNU General Public License.
|
||||
dnl They are *not* in the public domain.
|
||||
|
||||
dnl Authors:
|
||||
dnl Ulrich Drepper <drepper@cygnus.com>, 1995.
|
||||
|
||||
# Check whether LC_MESSAGES is available in <locale.h>.
|
||||
|
||||
AC_DEFUN([AM_LC_MESSAGES],
|
||||
[
|
||||
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, 1,
|
||||
[Define if your <locale.h> file defines LC_MESSAGES.])
|
||||
fi
|
||||
])
|
||||
m4_include([../config/acx.m4])
|
||||
m4_include([../config/codeset.m4])
|
||||
m4_include([../config/gettext-sister.m4])
|
||||
m4_include([../config/iconv.m4])
|
||||
m4_include([../config/lcmessage.m4])
|
||||
m4_include([../config/lib-ld.m4])
|
||||
m4_include([../config/lib-link.m4])
|
||||
m4_include([../config/lib-prefix.m4])
|
||||
m4_include([../config/progtest.m4])
|
||||
m4_include([acinclude.m4])
|
||||
|
81
contrib/gcc/addresses.h
Normal file
81
contrib/gcc/addresses.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* Inline functions to test validity of reg classes for addressing modes.
|
||||
Copyright (C) 2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Wrapper function to unify target macros MODE_CODE_BASE_REG_CLASS,
|
||||
MODE_BASE_REG_REG_CLASS, MODE_BASE_REG_CLASS and BASE_REG_CLASS.
|
||||
Arguments as for the MODE_CODE_BASE_REG_CLASS macro. */
|
||||
|
||||
static inline enum reg_class
|
||||
base_reg_class (enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||
enum rtx_code outer_code ATTRIBUTE_UNUSED,
|
||||
enum rtx_code index_code ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef MODE_CODE_BASE_REG_CLASS
|
||||
return MODE_CODE_BASE_REG_CLASS (mode, outer_code, index_code);
|
||||
#else
|
||||
#ifdef MODE_BASE_REG_REG_CLASS
|
||||
if (index_code == REG)
|
||||
return MODE_BASE_REG_REG_CLASS (mode);
|
||||
#endif
|
||||
#ifdef MODE_BASE_REG_CLASS
|
||||
return MODE_BASE_REG_CLASS (mode);
|
||||
#else
|
||||
return BASE_REG_CLASS;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wrapper function to unify target macros REGNO_MODE_CODE_OK_FOR_BASE_P,
|
||||
REGNO_MODE_OK_FOR_REG_BASE_P, REGNO_MODE_OK_FOR_BASE_P and
|
||||
REGNO_OK_FOR_BASE_P.
|
||||
Arguments as for the REGNO_MODE_CODE_OK_FOR_BASE_P macro. */
|
||||
|
||||
static inline bool
|
||||
ok_for_base_p_1 (unsigned regno, enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||
enum rtx_code outer_code ATTRIBUTE_UNUSED,
|
||||
enum rtx_code index_code ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifdef REGNO_MODE_CODE_OK_FOR_BASE_P
|
||||
return REGNO_MODE_CODE_OK_FOR_BASE_P (regno, mode, outer_code, index_code);
|
||||
#else
|
||||
#ifdef REGNO_MODE_OK_FOR_REG_BASE_P
|
||||
if (index_code == REG)
|
||||
return REGNO_MODE_OK_FOR_REG_BASE_P (regno, mode);
|
||||
#endif
|
||||
#ifdef REGNO_MODE_OK_FOR_BASE_P
|
||||
return REGNO_MODE_OK_FOR_BASE_P (regno, mode);
|
||||
#else
|
||||
return REGNO_OK_FOR_BASE_P (regno);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wrapper around ok_for_base_p_1, for use after register allocation is
|
||||
complete. Arguments as for the called function. */
|
||||
|
||||
static inline bool
|
||||
regno_ok_for_base_p (unsigned regno, enum machine_mode mode,
|
||||
enum rtx_code outer_code, enum rtx_code index_code)
|
||||
{
|
||||
if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] >= 0)
|
||||
regno = reg_renumber[regno];
|
||||
|
||||
return ok_for_base_p_1 (regno, mode, outer_code, index_code);
|
||||
}
|
1005
contrib/gcc/alias.c
1005
contrib/gcc/alias.c
File diff suppressed because it is too large
Load Diff
35
contrib/gcc/alias.h
Normal file
35
contrib/gcc/alias.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* Exported functions from alias.c
|
||||
Copyright (C) 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_ALIAS_H
|
||||
#define GCC_ALIAS_H
|
||||
|
||||
extern HOST_WIDE_INT new_alias_set (void);
|
||||
extern HOST_WIDE_INT get_varargs_alias_set (void);
|
||||
extern HOST_WIDE_INT get_frame_alias_set (void);
|
||||
extern bool component_uses_parent_alias_set (tree);
|
||||
|
||||
/* This alias set can be used to force a memory to conflict with all
|
||||
other memories, creating a barrier across which no memory reference
|
||||
can move. Note that there are other legacy ways to create such
|
||||
memory barriers, including an address of SCRATCH. */
|
||||
#define ALIAS_SET_MEMORY_BARRIER ((HOST_WIDE_INT) -1)
|
||||
|
||||
#endif /* GCC_ALIAS_H */
|
@ -1,5 +1,5 @@
|
||||
/* Functions to support a pool of allocatable objects.
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003, 2004
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Daniel Berlin <dan@cgsoftware.com>
|
||||
|
||||
@ -17,24 +17,14 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "hashtab.h"
|
||||
|
||||
/* Redefine abort to report an internal error w/o coredump, and
|
||||
reporting the location of the error in the source file. This logic
|
||||
is duplicated in rtl.h and tree.h because every file that needs the
|
||||
special abort includes one or both. toplev.h gets too few files,
|
||||
system.h gets too many. */
|
||||
|
||||
extern void fancy_abort (const char *, int, const char *)
|
||||
ATTRIBUTE_NORETURN;
|
||||
#define abort() fancy_abort (__FILE__, __LINE__, __FUNCTION__)
|
||||
|
||||
#define align_eight(x) (((x+7) >> 3) << 3)
|
||||
|
||||
/* The internal allocation object. */
|
||||
@ -75,7 +65,7 @@ static ALLOC_POOL_ID_TYPE last_id;
|
||||
|
||||
#ifdef GATHER_STATISTICS
|
||||
|
||||
/* Store infromation about each particular alloc_pool. */
|
||||
/* Store information about each particular alloc_pool. */
|
||||
struct alloc_pool_descriptor
|
||||
{
|
||||
const char *name;
|
||||
@ -113,7 +103,7 @@ alloc_pool_descriptor (const char *name)
|
||||
|
||||
slot = (struct alloc_pool_descriptor **)
|
||||
htab_find_slot_with_hash (alloc_pool_hash, name,
|
||||
htab_hash_pointer (name),
|
||||
htab_hash_pointer (name),
|
||||
1);
|
||||
if (*slot)
|
||||
return *slot;
|
||||
@ -135,8 +125,7 @@ create_alloc_pool (const char *name, size_t size, size_t num)
|
||||
struct alloc_pool_descriptor *desc;
|
||||
#endif
|
||||
|
||||
if (!name)
|
||||
abort ();
|
||||
gcc_assert (name);
|
||||
|
||||
/* Make size large enough to store the list header. */
|
||||
if (size < sizeof (alloc_pool_list))
|
||||
@ -151,8 +140,7 @@ create_alloc_pool (const char *name, size_t size, size_t num)
|
||||
#endif
|
||||
|
||||
/* Um, we can't really allocate 0 elements per block. */
|
||||
if (num == 0)
|
||||
abort ();
|
||||
gcc_assert (num);
|
||||
|
||||
/* Find the size of the pool structure, and the name. */
|
||||
pool_size = sizeof (struct alloc_pool_def);
|
||||
@ -201,10 +189,7 @@ free_alloc_pool (alloc_pool pool)
|
||||
struct alloc_pool_descriptor *desc = alloc_pool_descriptor (pool->name);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (!pool)
|
||||
abort ();
|
||||
#endif
|
||||
gcc_assert (pool);
|
||||
|
||||
/* Free each block allocated to the pool. */
|
||||
for (block = pool->block_list; block != NULL; block = next_block)
|
||||
@ -215,13 +200,24 @@ free_alloc_pool (alloc_pool pool)
|
||||
desc->current -= pool->block_size;
|
||||
#endif
|
||||
}
|
||||
/* Lastly, free the pool. */
|
||||
#ifdef ENABLE_CHECKING
|
||||
memset (pool, 0xaf, sizeof (*pool));
|
||||
#endif
|
||||
/* Lastly, free the pool. */
|
||||
free (pool);
|
||||
}
|
||||
|
||||
/* Frees the alloc_pool, if it is empty and zero *POOL in this case. */
|
||||
void
|
||||
free_alloc_pool_if_empty (alloc_pool *pool)
|
||||
{
|
||||
if ((*pool)->elts_free == (*pool)->elts_allocated)
|
||||
{
|
||||
free_alloc_pool (*pool);
|
||||
*pool = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocates one element from the pool specified. */
|
||||
void *
|
||||
pool_alloc (alloc_pool pool)
|
||||
@ -234,10 +230,7 @@ pool_alloc (alloc_pool pool)
|
||||
desc->allocated+=pool->elt_size;
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (!pool)
|
||||
abort ();
|
||||
#endif
|
||||
gcc_assert (pool);
|
||||
|
||||
/* If there are no more free elements, make some more!. */
|
||||
if (!pool->free_list)
|
||||
@ -246,7 +239,7 @@ pool_alloc (alloc_pool pool)
|
||||
alloc_pool_list block_header;
|
||||
|
||||
/* Make the block. */
|
||||
block = xmalloc (pool->block_size);
|
||||
block = XNEWVEC (char, pool->block_size);
|
||||
block_header = (alloc_pool_list) block;
|
||||
block += align_eight (sizeof (struct alloc_pool_list_def));
|
||||
#ifdef GATHER_STATISTICS
|
||||
@ -266,12 +259,12 @@ pool_alloc (alloc_pool pool)
|
||||
/* Mark the element to be free. */
|
||||
((allocation_object *) block)->id = 0;
|
||||
#endif
|
||||
header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
|
||||
header->next = pool->free_list;
|
||||
pool->free_list = header;
|
||||
header = (alloc_pool_list) USER_PTR_FROM_ALLOCATION_OBJECT_PTR (block);
|
||||
header->next = pool->free_list;
|
||||
pool->free_list = header;
|
||||
}
|
||||
/* Also update the number of elements we have free/allocated, and
|
||||
increment the allocated block count. */
|
||||
increment the allocated block count. */
|
||||
pool->elts_allocated += pool->elts_per_block;
|
||||
pool->elts_free += pool->elts_per_block;
|
||||
pool->blocks_allocated += 1;
|
||||
@ -296,22 +289,19 @@ pool_free (alloc_pool pool, void *ptr)
|
||||
{
|
||||
alloc_pool_list header;
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
if (!ptr)
|
||||
abort ();
|
||||
gcc_assert (ptr);
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
memset (ptr, 0xaf, pool->elt_size - offsetof (allocation_object, u.data));
|
||||
|
||||
/* Check whether the PTR was allocated from POOL. */
|
||||
if (pool->id != ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id)
|
||||
abort ();
|
||||
gcc_assert (pool->id == ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id);
|
||||
|
||||
/* Mark the element to be free. */
|
||||
ALLOCATION_OBJECT_PTR_FROM_USER_PTR (ptr)->id = 0;
|
||||
#else
|
||||
/* Check if we free more than we allocated, which is Bad (TM). */
|
||||
if (pool->elts_free + 1 > pool->elts_allocated)
|
||||
abort ();
|
||||
gcc_assert (pool->elts_free < pool->elts_allocated);
|
||||
#endif
|
||||
|
||||
header = (alloc_pool_list) ptr;
|
||||
@ -349,11 +339,15 @@ print_statistics (void **slot, void *b)
|
||||
#endif
|
||||
|
||||
/* Output per-alloc_pool memory usage statistics. */
|
||||
void dump_alloc_pool_statistics (void)
|
||||
void
|
||||
dump_alloc_pool_statistics (void)
|
||||
{
|
||||
#ifdef GATHER_STATISTICS
|
||||
struct output_info info;
|
||||
|
||||
if (!alloc_pool_hash)
|
||||
return;
|
||||
|
||||
fprintf (stderr, "\nAlloc-pool Kind Pools Allocated Peak Leak\n");
|
||||
fprintf (stderr, "-------------------------------------------------------------\n");
|
||||
info.count = 0;
|
||||
|
@ -17,8 +17,8 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
#ifndef ALLOC_POOL_H
|
||||
#define ALLOC_POOL_H
|
||||
|
||||
@ -49,6 +49,7 @@ typedef struct alloc_pool_def
|
||||
|
||||
extern alloc_pool create_alloc_pool (const char *, size_t, size_t);
|
||||
extern void free_alloc_pool (alloc_pool);
|
||||
extern void free_alloc_pool_if_empty (alloc_pool *);
|
||||
extern void *pool_alloc (alloc_pool);
|
||||
extern void pool_free (alloc_pool, void *);
|
||||
extern void dump_alloc_pool_statistics (void);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Functions dealing with attribute handling, used by most front ends.
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003 Free Software Foundation, Inc.
|
||||
2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -29,7 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "output.h"
|
||||
#include "rtl.h"
|
||||
#include "ggc.h"
|
||||
#include "expr.h"
|
||||
#include "tm_p.h"
|
||||
#include "cpplib.h"
|
||||
#include "target.h"
|
||||
@ -78,25 +77,25 @@ init_attributes (void)
|
||||
/* The name must not begin and end with __. */
|
||||
const char *name = attribute_tables[i][j].name;
|
||||
int len = strlen (name);
|
||||
if (name[0] == '_' && name[1] == '_'
|
||||
&& name[len - 1] == '_' && name[len - 2] == '_')
|
||||
abort ();
|
||||
|
||||
gcc_assert (!(name[0] == '_' && name[1] == '_'
|
||||
&& name[len - 1] == '_' && name[len - 2] == '_'));
|
||||
|
||||
/* The minimum and maximum lengths must be consistent. */
|
||||
if (attribute_tables[i][j].min_length < 0)
|
||||
abort ();
|
||||
if (attribute_tables[i][j].max_length != -1
|
||||
&& (attribute_tables[i][j].max_length
|
||||
< attribute_tables[i][j].min_length))
|
||||
abort ();
|
||||
gcc_assert (attribute_tables[i][j].min_length >= 0);
|
||||
|
||||
gcc_assert (attribute_tables[i][j].max_length == -1
|
||||
|| (attribute_tables[i][j].max_length
|
||||
>= attribute_tables[i][j].min_length));
|
||||
|
||||
/* An attribute cannot require both a DECL and a TYPE. */
|
||||
if (attribute_tables[i][j].decl_required
|
||||
&& attribute_tables[i][j].type_required)
|
||||
abort ();
|
||||
gcc_assert (!attribute_tables[i][j].decl_required
|
||||
|| !attribute_tables[i][j].type_required);
|
||||
|
||||
/* If an attribute requires a function type, in particular
|
||||
it requires a type. */
|
||||
if (attribute_tables[i][j].function_type_required
|
||||
&& !attribute_tables[i][j].type_required)
|
||||
abort ();
|
||||
gcc_assert (!attribute_tables[i][j].function_type_required
|
||||
|| attribute_tables[i][j].type_required);
|
||||
}
|
||||
}
|
||||
|
||||
@ -106,9 +105,8 @@ init_attributes (void)
|
||||
int j, k;
|
||||
for (j = 0; attribute_tables[i][j].name != NULL; j++)
|
||||
for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
|
||||
if (!strcmp (attribute_tables[i][j].name,
|
||||
attribute_tables[i][k].name))
|
||||
abort ();
|
||||
gcc_assert (strcmp (attribute_tables[i][j].name,
|
||||
attribute_tables[i][k].name));
|
||||
}
|
||||
/* Check that no name occurs in more than one table. */
|
||||
for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
|
||||
@ -118,9 +116,8 @@ init_attributes (void)
|
||||
for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
|
||||
for (k = 0; attribute_tables[i][k].name != NULL; k++)
|
||||
for (l = 0; attribute_tables[j][l].name != NULL; l++)
|
||||
if (!strcmp (attribute_tables[i][k].name,
|
||||
attribute_tables[j][l].name))
|
||||
abort ();
|
||||
gcc_assert (strcmp (attribute_tables[i][k].name,
|
||||
attribute_tables[j][l].name));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -145,7 +142,7 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
if (!attributes_initialized)
|
||||
init_attributes ();
|
||||
|
||||
(*targetm.insert_attributes) (*node, &attributes);
|
||||
targetm.insert_attributes (*node, &attributes);
|
||||
|
||||
for (a = attributes; a; a = TREE_CHAIN (a))
|
||||
{
|
||||
@ -175,7 +172,7 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
|
||||
if (spec == NULL)
|
||||
{
|
||||
warning ("`%s' attribute directive ignored",
|
||||
warning (OPT_Wattributes, "%qs attribute directive ignored",
|
||||
IDENTIFIER_POINTER (name));
|
||||
continue;
|
||||
}
|
||||
@ -183,7 +180,7 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
|| (spec->max_length >= 0
|
||||
&& list_length (args) > spec->max_length))
|
||||
{
|
||||
error ("wrong number of arguments specified for `%s' attribute",
|
||||
error ("wrong number of arguments specified for %qs attribute",
|
||||
IDENTIFIER_POINTER (name));
|
||||
continue;
|
||||
}
|
||||
@ -200,7 +197,7 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
}
|
||||
else
|
||||
{
|
||||
warning ("`%s' attribute does not apply to types",
|
||||
warning (OPT_Wattributes, "%qs attribute does not apply to types",
|
||||
IDENTIFIER_POINTER (name));
|
||||
continue;
|
||||
}
|
||||
@ -230,8 +227,8 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
pull out the target type now, frob it as appropriate, and
|
||||
rebuild the pointer type later.
|
||||
|
||||
This would all be simpler if attributes were part of the
|
||||
declarator, grumble grumble. */
|
||||
This would all be simpler if attributes were part of the
|
||||
declarator, grumble grumble. */
|
||||
fn_ptr_tmp = TREE_TYPE (*anode);
|
||||
anode = &fn_ptr_tmp;
|
||||
flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
|
||||
@ -246,12 +243,21 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
if (TREE_CODE (*anode) != FUNCTION_TYPE
|
||||
&& TREE_CODE (*anode) != METHOD_TYPE)
|
||||
{
|
||||
warning ("`%s' attribute only applies to function types",
|
||||
warning (OPT_Wattributes,
|
||||
"%qs attribute only applies to function types",
|
||||
IDENTIFIER_POINTER (name));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (TYPE_P (*anode)
|
||||
&& (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
|
||||
&& TYPE_SIZE (*anode) != NULL_TREE)
|
||||
{
|
||||
warning (OPT_Wattributes, "type attributes ignored after type is already defined");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (spec->handler != NULL)
|
||||
returned_attrs = chainon ((*spec->handler) (anode, name, args,
|
||||
flags, &no_add_attrs),
|
||||
@ -262,15 +268,7 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
&& (TREE_CODE (*node) == VAR_DECL
|
||||
|| TREE_CODE (*node) == PARM_DECL
|
||||
|| TREE_CODE (*node) == RESULT_DECL))
|
||||
{
|
||||
/* Force a recalculation of mode and size. */
|
||||
DECL_MODE (*node) = VOIDmode;
|
||||
DECL_SIZE (*node) = 0;
|
||||
if (!DECL_USER_ALIGN (*node))
|
||||
DECL_ALIGN (*node) = 0;
|
||||
|
||||
layout_decl (*node, 0);
|
||||
}
|
||||
relayout_decl (*node);
|
||||
|
||||
if (!no_add_attrs)
|
||||
{
|
||||
@ -296,7 +294,26 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
if (DECL_P (*anode))
|
||||
DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
|
||||
else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
|
||||
TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
|
||||
{
|
||||
TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
|
||||
/* If this is the main variant, also push the attributes
|
||||
out to the other variants. */
|
||||
if (*anode == TYPE_MAIN_VARIANT (*anode))
|
||||
{
|
||||
tree variant;
|
||||
for (variant = *anode; variant;
|
||||
variant = TYPE_NEXT_VARIANT (variant))
|
||||
{
|
||||
if (TYPE_ATTRIBUTES (variant) == old_attrs)
|
||||
TYPE_ATTRIBUTES (variant)
|
||||
= TYPE_ATTRIBUTES (*anode);
|
||||
else if (!lookup_attribute
|
||||
(spec->name, TYPE_ATTRIBUTES (variant)))
|
||||
TYPE_ATTRIBUTES (variant) = tree_cons
|
||||
(name, args, TYPE_ATTRIBUTES (variant));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
*anode = build_type_attribute_variant (*anode,
|
||||
tree_cons (name, args,
|
||||
@ -311,114 +328,13 @@ decl_attributes (tree *node, tree attributes, int flags)
|
||||
fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
|
||||
if (DECL_P (*node))
|
||||
TREE_TYPE (*node) = fn_ptr_tmp;
|
||||
else if (TREE_CODE (*node) == POINTER_TYPE)
|
||||
*node = fn_ptr_tmp;
|
||||
else
|
||||
abort ();
|
||||
{
|
||||
gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
|
||||
*node = fn_ptr_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returned_attrs;
|
||||
}
|
||||
|
||||
/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
|
||||
lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
|
||||
|
||||
The head of the declspec list is stored in DECLSPECS.
|
||||
The head of the attribute list is stored in PREFIX_ATTRIBUTES.
|
||||
|
||||
Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
|
||||
the list elements. We drop the containing TREE_LIST nodes and link the
|
||||
resulting attributes together the way decl_attributes expects them. */
|
||||
|
||||
void
|
||||
split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes)
|
||||
{
|
||||
tree t, s, a, next, specs, attrs;
|
||||
|
||||
/* This can happen after an __extension__ in pedantic mode. */
|
||||
if (specs_attrs != NULL_TREE
|
||||
&& TREE_CODE (specs_attrs) == INTEGER_CST)
|
||||
{
|
||||
*declspecs = NULL_TREE;
|
||||
*prefix_attributes = NULL_TREE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* This can happen in c++ (eg: decl: typespec initdecls ';'). */
|
||||
if (specs_attrs != NULL_TREE
|
||||
&& TREE_CODE (specs_attrs) != TREE_LIST)
|
||||
{
|
||||
*declspecs = specs_attrs;
|
||||
*prefix_attributes = NULL_TREE;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remember to keep the lists in the same order, element-wise. */
|
||||
|
||||
specs = s = NULL_TREE;
|
||||
attrs = a = NULL_TREE;
|
||||
for (t = specs_attrs; t; t = next)
|
||||
{
|
||||
next = TREE_CHAIN (t);
|
||||
/* Declspecs have a non-NULL TREE_VALUE. */
|
||||
if (TREE_VALUE (t) != NULL_TREE)
|
||||
{
|
||||
if (specs == NULL_TREE)
|
||||
specs = s = t;
|
||||
else
|
||||
{
|
||||
TREE_CHAIN (s) = t;
|
||||
s = t;
|
||||
}
|
||||
}
|
||||
/* The TREE_PURPOSE may also be empty in the case of
|
||||
__attribute__(()). */
|
||||
else if (TREE_PURPOSE (t) != NULL_TREE)
|
||||
{
|
||||
if (attrs == NULL_TREE)
|
||||
attrs = a = TREE_PURPOSE (t);
|
||||
else
|
||||
{
|
||||
TREE_CHAIN (a) = TREE_PURPOSE (t);
|
||||
a = TREE_PURPOSE (t);
|
||||
}
|
||||
/* More attrs can be linked here, move A to the end. */
|
||||
while (TREE_CHAIN (a) != NULL_TREE)
|
||||
a = TREE_CHAIN (a);
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate the lists. */
|
||||
if (s != NULL_TREE)
|
||||
TREE_CHAIN (s) = NULL_TREE;
|
||||
if (a != NULL_TREE)
|
||||
TREE_CHAIN (a) = NULL_TREE;
|
||||
|
||||
/* All done. */
|
||||
*declspecs = specs;
|
||||
*prefix_attributes = attrs;
|
||||
}
|
||||
|
||||
/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes.
|
||||
This function is used by the parser when a rule will accept attributes
|
||||
in a particular position, but we don't want to support that just yet.
|
||||
|
||||
A warning is issued for every ignored attribute. */
|
||||
|
||||
tree
|
||||
strip_attrs (tree specs_attrs)
|
||||
{
|
||||
tree specs, attrs;
|
||||
|
||||
split_specs_attrs (specs_attrs, &specs, &attrs);
|
||||
|
||||
while (attrs)
|
||||
{
|
||||
warning ("`%s' attribute ignored",
|
||||
IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
|
||||
attrs = TREE_CHAIN (attrs);
|
||||
}
|
||||
|
||||
return specs;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1556
contrib/gcc/bitmap.c
1556
contrib/gcc/bitmap.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Functions to support general ended bitmaps.
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,37 +16,49 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_BITMAP_H
|
||||
#define GCC_BITMAP_H
|
||||
#include "hashtab.h"
|
||||
|
||||
/* Fundamental storage type for bitmap. */
|
||||
|
||||
/* typedef unsigned HOST_WIDE_INT BITMAP_WORD; */
|
||||
/* #define nBITMAP_WORD_BITS HOST_BITS_PER_WIDE_INT */
|
||||
typedef unsigned long BITMAP_WORD;
|
||||
#define nBITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG)
|
||||
#define BITMAP_WORD_BITS (unsigned) nBITMAP_WORD_BITS
|
||||
/* BITMAP_WORD_BITS needs to be unsigned, but cannot contain casts as
|
||||
it is used in preprocessor directives -- hence the 1u. */
|
||||
#define BITMAP_WORD_BITS (CHAR_BIT * SIZEOF_LONG * 1u)
|
||||
|
||||
/* Number of words to use for each element in the linked list. */
|
||||
|
||||
#ifndef BITMAP_ELEMENT_WORDS
|
||||
#define BITMAP_ELEMENT_WORDS ((128 + nBITMAP_WORD_BITS - 1) / nBITMAP_WORD_BITS)
|
||||
#define BITMAP_ELEMENT_WORDS ((128 + BITMAP_WORD_BITS - 1) / BITMAP_WORD_BITS)
|
||||
#endif
|
||||
|
||||
/* Number of bits in each actual element of a bitmap. We get slightly better
|
||||
code for bit % BITMAP_ELEMENT_ALL_BITS and bit / BITMAP_ELEMENT_ALL_BITS if
|
||||
bits is unsigned, assuming it is a power of 2. */
|
||||
/* Number of bits in each actual element of a bitmap. */
|
||||
|
||||
#define BITMAP_ELEMENT_ALL_BITS \
|
||||
((unsigned) (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS))
|
||||
#define BITMAP_ELEMENT_ALL_BITS (BITMAP_ELEMENT_WORDS * BITMAP_WORD_BITS)
|
||||
|
||||
/* Obstack for allocating bitmaps and elements from. */
|
||||
typedef struct bitmap_obstack GTY (())
|
||||
{
|
||||
struct bitmap_element_def *elements;
|
||||
struct bitmap_head_def *heads;
|
||||
struct obstack GTY ((skip)) obstack;
|
||||
} bitmap_obstack;
|
||||
|
||||
/* Bitmap set element. We use a linked list to hold only the bits that
|
||||
are set. This allows for use to grow the bitset dynamically without
|
||||
having to realloc and copy a giant bit array. The `prev' field is
|
||||
undefined for an element on the free list. */
|
||||
having to realloc and copy a giant bit array.
|
||||
|
||||
The free list is implemented as a list of lists. There is one
|
||||
outer list connected together by prev fields. Each element of that
|
||||
outer is an inner list (that may consist only of the outer list
|
||||
element) that are connected by the next fields. The prev pointer
|
||||
is undefined for interior elements. This allows
|
||||
bitmap_elt_clear_from to be implemented in unit time rather than
|
||||
linear in the number of elements to be freed. */
|
||||
|
||||
typedef struct bitmap_element_def GTY(())
|
||||
{
|
||||
@ -61,22 +73,14 @@ typedef struct bitmap_head_def GTY(()) {
|
||||
bitmap_element *first; /* First element in linked list. */
|
||||
bitmap_element *current; /* Last element looked at. */
|
||||
unsigned int indx; /* Index of last element looked at. */
|
||||
int using_obstack; /* Are we using an obstack or ggc for
|
||||
allocation? */
|
||||
bitmap_obstack *obstack; /* Obstack to allocate elements from.
|
||||
If NULL, then use ggc_alloc. */
|
||||
} bitmap_head;
|
||||
typedef struct bitmap_head_def *bitmap;
|
||||
|
||||
/* Enumeration giving the various operations we support. */
|
||||
enum bitmap_bits {
|
||||
BITMAP_AND, /* TO = FROM1 & FROM2 */
|
||||
BITMAP_AND_COMPL, /* TO = FROM1 & ~ FROM2 */
|
||||
BITMAP_IOR, /* TO = FROM1 | FROM2 */
|
||||
BITMAP_XOR, /* TO = FROM1 ^ FROM2 */
|
||||
BITMAP_IOR_COMPL /* TO = FROM1 | ~FROM2 */
|
||||
};
|
||||
|
||||
/* Global data */
|
||||
extern bitmap_element bitmap_zero_bits; /* Zero bitmap element */
|
||||
extern bitmap_obstack bitmap_default_obstack; /* Default bitmap obstack */
|
||||
|
||||
/* Clear a bitmap by freeing up the linked list. */
|
||||
extern void bitmap_clear (bitmap);
|
||||
@ -85,14 +89,41 @@ extern void bitmap_clear (bitmap);
|
||||
extern void bitmap_copy (bitmap, bitmap);
|
||||
|
||||
/* True if two bitmaps are identical. */
|
||||
extern int bitmap_equal_p (bitmap, bitmap);
|
||||
extern bool bitmap_equal_p (bitmap, bitmap);
|
||||
|
||||
/* Perform an operation on two bitmaps, yielding a third. */
|
||||
extern int bitmap_operation (bitmap, bitmap, bitmap, enum bitmap_bits);
|
||||
/* True if the bitmaps intersect (their AND is non-empty). */
|
||||
extern bool bitmap_intersect_p (bitmap, bitmap);
|
||||
|
||||
/* `or' into one bitmap the `and' of a second bitmap witih the complement
|
||||
of a third. */
|
||||
extern void bitmap_ior_and_compl (bitmap, bitmap, bitmap);
|
||||
/* True if the complement of the second intersects the first (their
|
||||
AND_COMPL is non-empty). */
|
||||
extern bool bitmap_intersect_compl_p (bitmap, bitmap);
|
||||
|
||||
/* True if MAP is an empty bitmap. */
|
||||
#define bitmap_empty_p(MAP) (!(MAP)->first)
|
||||
|
||||
/* Count the number of bits set in the bitmap. */
|
||||
extern unsigned long bitmap_count_bits (bitmap);
|
||||
|
||||
/* Boolean operations on bitmaps. The _into variants are two operand
|
||||
versions that modify the first source operand. The other variants
|
||||
are three operand versions that to not destroy the source bitmaps.
|
||||
The operations supported are &, & ~, |, ^. */
|
||||
extern void bitmap_and (bitmap, bitmap, bitmap);
|
||||
extern void bitmap_and_into (bitmap, bitmap);
|
||||
extern void bitmap_and_compl (bitmap, bitmap, bitmap);
|
||||
extern bool bitmap_and_compl_into (bitmap, bitmap);
|
||||
#define bitmap_compl_and(DST, A, B) bitmap_and_compl (DST, B, A)
|
||||
extern void bitmap_compl_and_into (bitmap, bitmap);
|
||||
extern void bitmap_clear_range (bitmap, unsigned int, unsigned int);
|
||||
extern bool bitmap_ior (bitmap, bitmap, bitmap);
|
||||
extern bool bitmap_ior_into (bitmap, bitmap);
|
||||
extern void bitmap_xor (bitmap, bitmap, bitmap);
|
||||
extern void bitmap_xor_into (bitmap, bitmap);
|
||||
|
||||
/* DST = A | (B & ~C). Return true if DST changes. */
|
||||
extern bool bitmap_ior_and_compl (bitmap DST, bitmap A, bitmap B, bitmap C);
|
||||
/* A |= (B & ~C). Return true if A changes. */
|
||||
extern bool bitmap_ior_and_compl_into (bitmap DST, bitmap B, bitmap C);
|
||||
|
||||
/* Clear a single register in a register set. */
|
||||
extern void bitmap_clear_bit (bitmap, int);
|
||||
@ -110,246 +141,428 @@ extern void debug_bitmap_file (FILE *, bitmap);
|
||||
/* Print a bitmap. */
|
||||
extern void bitmap_print (FILE *, bitmap, const char *, const char *);
|
||||
|
||||
/* Initialize a bitmap header. If HEAD is NULL, a new header will be
|
||||
allocated. USING_OBSTACK indicates how elements should be allocated. */
|
||||
extern bitmap bitmap_initialize (bitmap head, int using_obstack);
|
||||
/* Initialize and release a bitmap obstack. */
|
||||
extern void bitmap_obstack_initialize (bitmap_obstack *);
|
||||
extern void bitmap_obstack_release (bitmap_obstack *);
|
||||
|
||||
/* Release all memory used by the bitmap obstack. */
|
||||
extern void bitmap_release_memory (void);
|
||||
/* Initialize a bitmap header. OBSTACK indicates the bitmap obstack
|
||||
to allocate from, NULL for GC'd bitmap. */
|
||||
|
||||
static inline void
|
||||
bitmap_initialize (bitmap head, bitmap_obstack *obstack)
|
||||
{
|
||||
head->first = head->current = NULL;
|
||||
head->obstack = obstack;
|
||||
}
|
||||
|
||||
/* Allocate and free bitmaps from obstack, malloc and gc'd memory. */
|
||||
extern bitmap bitmap_obstack_alloc (bitmap_obstack *obstack);
|
||||
extern bitmap bitmap_gc_alloc (void);
|
||||
extern void bitmap_obstack_free (bitmap);
|
||||
|
||||
/* A few compatibility/functions macros for compatibility with sbitmaps */
|
||||
#define dump_bitmap(file, bitmap) bitmap_print (file, bitmap, "", "\n")
|
||||
#define bitmap_zero(a) bitmap_clear (a)
|
||||
#define bitmap_a_or_b(a,b,c) bitmap_operation (a, b, c, BITMAP_IOR)
|
||||
#define bitmap_a_and_b(a,b,c) bitmap_operation (a, b, c, BITMAP_AND)
|
||||
extern int bitmap_union_of_diff (bitmap, bitmap, bitmap, bitmap);
|
||||
extern int bitmap_first_set_bit (bitmap);
|
||||
extern int bitmap_last_set_bit (bitmap);
|
||||
extern unsigned bitmap_first_set_bit (bitmap);
|
||||
|
||||
/* Allocate a bitmap with oballoc. */
|
||||
#define BITMAP_OBSTACK_ALLOC(OBSTACK) \
|
||||
bitmap_initialize (obstack_alloc (OBSTACK, sizeof (bitmap_head)), 1)
|
||||
/* Compute bitmap hash (for purposes of hashing etc.) */
|
||||
extern hashval_t bitmap_hash(bitmap);
|
||||
|
||||
/* Allocate a bitmap with ggc_alloc. */
|
||||
#define BITMAP_GGC_ALLOC() \
|
||||
bitmap_initialize (NULL, 0)
|
||||
/* Allocate a bitmap from a bit obstack. */
|
||||
#define BITMAP_ALLOC(OBSTACK) bitmap_obstack_alloc (OBSTACK)
|
||||
|
||||
/* Allocate a bitmap with xmalloc. */
|
||||
#define BITMAP_XMALLOC() \
|
||||
bitmap_initialize (xmalloc (sizeof (bitmap_head)), 1)
|
||||
/* Allocate a gc'd bitmap. */
|
||||
#define BITMAP_GGC_ALLOC() bitmap_gc_alloc ()
|
||||
|
||||
/* Do any cleanup needed on a bitmap when it is no longer used. */
|
||||
#define BITMAP_FREE(BITMAP) \
|
||||
do { \
|
||||
if (BITMAP) \
|
||||
{ \
|
||||
bitmap_clear (BITMAP); \
|
||||
(BITMAP) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
((void)(bitmap_obstack_free (BITMAP), (BITMAP) = NULL))
|
||||
|
||||
/* Do any cleanup needed on an xmalloced bitmap when it is no longer used. */
|
||||
#define BITMAP_XFREE(BITMAP) \
|
||||
do { \
|
||||
if (BITMAP) \
|
||||
{ \
|
||||
bitmap_clear (BITMAP); \
|
||||
free (BITMAP); \
|
||||
(BITMAP) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
/* Iterator for bitmaps. */
|
||||
|
||||
/* Do any one-time initializations needed for bitmaps. */
|
||||
#define BITMAP_INIT_ONCE()
|
||||
typedef struct
|
||||
{
|
||||
/* Pointer to the current bitmap element. */
|
||||
bitmap_element *elt1;
|
||||
|
||||
/* Loop over all bits in BITMAP, starting with MIN, setting BITNUM to the
|
||||
bit number and executing CODE for all bits that are set. */
|
||||
/* Pointer to 2nd bitmap element when two are involved. */
|
||||
bitmap_element *elt2;
|
||||
|
||||
#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, CODE) \
|
||||
do { \
|
||||
bitmap_element *ptr_ = (BITMAP)->first; \
|
||||
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
|
||||
unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
|
||||
unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
|
||||
\
|
||||
\
|
||||
/* Find the block the minimum bit is in. */ \
|
||||
while (ptr_ != 0 && ptr_->indx < indx_) \
|
||||
ptr_ = ptr_->next; \
|
||||
\
|
||||
if (ptr_ != 0 && ptr_->indx != indx_) \
|
||||
{ \
|
||||
bit_num_ = 0; \
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
for (; ptr_ != 0; ptr_ = ptr_->next) \
|
||||
{ \
|
||||
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD word_ = ptr_->bits[word_num_]; \
|
||||
\
|
||||
if (word_ != 0) \
|
||||
{ \
|
||||
for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
|
||||
\
|
||||
if ((word_ & mask_) != 0) \
|
||||
{ \
|
||||
word_ &= ~ mask_; \
|
||||
(BITNUM) = (ptr_->indx * BITMAP_ELEMENT_ALL_BITS \
|
||||
+ word_num_ * BITMAP_WORD_BITS \
|
||||
+ bit_num_); \
|
||||
CODE; \
|
||||
\
|
||||
if (word_ == 0) \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bit_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
/* Word within the current element. */
|
||||
unsigned word_no;
|
||||
|
||||
/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting
|
||||
BITNUM to the bit number and executing CODE for all bits that are set in
|
||||
the first bitmap and not set in the second. */
|
||||
/* Contents of the actually processed word. When finding next bit
|
||||
it is shifted right, so that the actual bit is always the least
|
||||
significant bit of ACTUAL. */
|
||||
BITMAP_WORD bits;
|
||||
} bitmap_iterator;
|
||||
|
||||
#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \
|
||||
do { \
|
||||
bitmap_element *ptr1_ = (BITMAP1)->first; \
|
||||
bitmap_element *ptr2_ = (BITMAP2)->first; \
|
||||
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
|
||||
unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
|
||||
unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
|
||||
\
|
||||
/* Find the block the minimum bit is in in the first bitmap. */ \
|
||||
while (ptr1_ != 0 && ptr1_->indx < indx_) \
|
||||
ptr1_ = ptr1_->next; \
|
||||
\
|
||||
if (ptr1_ != 0 && ptr1_->indx != indx_) \
|
||||
{ \
|
||||
bit_num_ = 0; \
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \
|
||||
{ \
|
||||
/* Advance BITMAP2 to the equivalent link, using an all \
|
||||
zero element if an equivalent link doesn't exist. */ \
|
||||
bitmap_element *tmp2_; \
|
||||
\
|
||||
while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \
|
||||
ptr2_ = ptr2_->next; \
|
||||
\
|
||||
tmp2_ = ((ptr2_ != 0 && ptr2_->indx == ptr1_->indx) \
|
||||
? ptr2_ : &bitmap_zero_bits); \
|
||||
\
|
||||
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD word_ = (ptr1_->bits[word_num_] \
|
||||
& ~ tmp2_->bits[word_num_]); \
|
||||
if (word_ != 0) \
|
||||
{ \
|
||||
for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
|
||||
\
|
||||
if ((word_ & mask_) != 0) \
|
||||
{ \
|
||||
word_ &= ~ mask_; \
|
||||
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
|
||||
+ word_num_ * BITMAP_WORD_BITS \
|
||||
+ bit_num_); \
|
||||
\
|
||||
CODE; \
|
||||
if (word_ == 0) \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bit_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
/* Initialize a single bitmap iterator. START_BIT is the first bit to
|
||||
iterate from. */
|
||||
|
||||
/* Loop over all bits in BITMAP1 and BITMAP2, starting with MIN, setting
|
||||
BITNUM to the bit number and executing CODE for all bits that are set in
|
||||
the both bitmaps. */
|
||||
static inline void
|
||||
bmp_iter_set_init (bitmap_iterator *bi, bitmap map,
|
||||
unsigned start_bit, unsigned *bit_no)
|
||||
{
|
||||
bi->elt1 = map->first;
|
||||
bi->elt2 = NULL;
|
||||
|
||||
#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, CODE) \
|
||||
do { \
|
||||
bitmap_element *ptr1_ = (BITMAP1)->first; \
|
||||
bitmap_element *ptr2_ = (BITMAP2)->first; \
|
||||
unsigned int indx_ = (MIN) / BITMAP_ELEMENT_ALL_BITS; \
|
||||
unsigned bit_num_ = (MIN) % BITMAP_WORD_BITS; \
|
||||
unsigned word_num_ = (MIN) / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS; \
|
||||
\
|
||||
/* Find the block the minimum bit is in in the first bitmap. */ \
|
||||
while (ptr1_ != 0 && ptr1_->indx < indx_) \
|
||||
ptr1_ = ptr1_->next; \
|
||||
\
|
||||
if (ptr1_ != 0 && ptr1_->indx != indx_) \
|
||||
{ \
|
||||
bit_num_ = 0; \
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
for (; ptr1_ != 0 ; ptr1_ = ptr1_->next) \
|
||||
{ \
|
||||
/* Advance BITMAP2 to the equivalent link. */ \
|
||||
while (ptr2_ != 0 && ptr2_->indx < ptr1_->indx) \
|
||||
ptr2_ = ptr2_->next; \
|
||||
\
|
||||
if (ptr2_ == 0) \
|
||||
{ \
|
||||
/* If there are no more elements in BITMAP2, exit loop now. */ \
|
||||
ptr1_ = (bitmap_element *)0; \
|
||||
break; \
|
||||
} \
|
||||
else if (ptr2_->indx > ptr1_->indx) \
|
||||
{ \
|
||||
bit_num_ = word_num_ = 0; \
|
||||
continue; \
|
||||
} \
|
||||
\
|
||||
for (; word_num_ < BITMAP_ELEMENT_WORDS; word_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD word_ = (ptr1_->bits[word_num_] \
|
||||
& ptr2_->bits[word_num_]); \
|
||||
if (word_ != 0) \
|
||||
{ \
|
||||
for (; bit_num_ < BITMAP_WORD_BITS; bit_num_++) \
|
||||
{ \
|
||||
BITMAP_WORD mask_ = ((BITMAP_WORD) 1) << bit_num_; \
|
||||
\
|
||||
if ((word_ & mask_) != 0) \
|
||||
{ \
|
||||
word_ &= ~ mask_; \
|
||||
(BITNUM) = (ptr1_->indx * BITMAP_ELEMENT_ALL_BITS \
|
||||
+ word_num_ * BITMAP_WORD_BITS \
|
||||
+ bit_num_); \
|
||||
\
|
||||
CODE; \
|
||||
if (word_ == 0) \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
bit_num_ = 0; \
|
||||
} \
|
||||
\
|
||||
word_num_ = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
/* Advance elt1 until it is not before the block containing start_bit. */
|
||||
while (1)
|
||||
{
|
||||
if (!bi->elt1)
|
||||
{
|
||||
bi->elt1 = &bitmap_zero_bits;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
break;
|
||||
bi->elt1 = bi->elt1->next;
|
||||
}
|
||||
|
||||
/* We might have gone past the start bit, so reinitialize it. */
|
||||
if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
|
||||
/* Initialize for what is now start_bit. */
|
||||
bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
|
||||
bi->bits = bi->elt1->bits[bi->word_no];
|
||||
bi->bits >>= start_bit % BITMAP_WORD_BITS;
|
||||
|
||||
/* If this word is zero, we must make sure we're not pointing at the
|
||||
first bit, otherwise our incrementing to the next word boundary
|
||||
will fail. It won't matter if this increment moves us into the
|
||||
next word. */
|
||||
start_bit += !bi->bits;
|
||||
|
||||
*bit_no = start_bit;
|
||||
}
|
||||
|
||||
/* Initialize an iterator to iterate over the intersection of two
|
||||
bitmaps. START_BIT is the bit to commence from. */
|
||||
|
||||
static inline void
|
||||
bmp_iter_and_init (bitmap_iterator *bi, bitmap map1, bitmap map2,
|
||||
unsigned start_bit, unsigned *bit_no)
|
||||
{
|
||||
bi->elt1 = map1->first;
|
||||
bi->elt2 = map2->first;
|
||||
|
||||
/* Advance elt1 until it is not before the block containing
|
||||
start_bit. */
|
||||
while (1)
|
||||
{
|
||||
if (!bi->elt1)
|
||||
{
|
||||
bi->elt2 = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
break;
|
||||
bi->elt1 = bi->elt1->next;
|
||||
}
|
||||
|
||||
/* Advance elt2 until it is not before elt1. */
|
||||
while (1)
|
||||
{
|
||||
if (!bi->elt2)
|
||||
{
|
||||
bi->elt1 = bi->elt2 = &bitmap_zero_bits;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi->elt2->indx >= bi->elt1->indx)
|
||||
break;
|
||||
bi->elt2 = bi->elt2->next;
|
||||
}
|
||||
|
||||
/* If we're at the same index, then we have some intersecting bits. */
|
||||
if (bi->elt1->indx == bi->elt2->indx)
|
||||
{
|
||||
/* We might have advanced beyond the start_bit, so reinitialize
|
||||
for that. */
|
||||
if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
|
||||
bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
|
||||
bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no];
|
||||
bi->bits >>= start_bit % BITMAP_WORD_BITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise we must immediately advance elt1, so initialize for
|
||||
that. */
|
||||
bi->word_no = BITMAP_ELEMENT_WORDS - 1;
|
||||
bi->bits = 0;
|
||||
}
|
||||
|
||||
/* If this word is zero, we must make sure we're not pointing at the
|
||||
first bit, otherwise our incrementing to the next word boundary
|
||||
will fail. It won't matter if this increment moves us into the
|
||||
next word. */
|
||||
start_bit += !bi->bits;
|
||||
|
||||
*bit_no = start_bit;
|
||||
}
|
||||
|
||||
/* Initialize an iterator to iterate over the bits in MAP1 & ~MAP2.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
bmp_iter_and_compl_init (bitmap_iterator *bi, bitmap map1, bitmap map2,
|
||||
unsigned start_bit, unsigned *bit_no)
|
||||
{
|
||||
bi->elt1 = map1->first;
|
||||
bi->elt2 = map2->first;
|
||||
|
||||
/* Advance elt1 until it is not before the block containing start_bit. */
|
||||
while (1)
|
||||
{
|
||||
if (!bi->elt1)
|
||||
{
|
||||
bi->elt1 = &bitmap_zero_bits;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bi->elt1->indx >= start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
break;
|
||||
bi->elt1 = bi->elt1->next;
|
||||
}
|
||||
|
||||
/* Advance elt2 until it is not before elt1. */
|
||||
while (bi->elt2 && bi->elt2->indx < bi->elt1->indx)
|
||||
bi->elt2 = bi->elt2->next;
|
||||
|
||||
/* We might have advanced beyond the start_bit, so reinitialize for
|
||||
that. */
|
||||
if (bi->elt1->indx != start_bit / BITMAP_ELEMENT_ALL_BITS)
|
||||
start_bit = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
|
||||
bi->word_no = start_bit / BITMAP_WORD_BITS % BITMAP_ELEMENT_WORDS;
|
||||
bi->bits = bi->elt1->bits[bi->word_no];
|
||||
if (bi->elt2 && bi->elt1->indx == bi->elt2->indx)
|
||||
bi->bits &= ~bi->elt2->bits[bi->word_no];
|
||||
bi->bits >>= start_bit % BITMAP_WORD_BITS;
|
||||
|
||||
/* If this word is zero, we must make sure we're not pointing at the
|
||||
first bit, otherwise our incrementing to the next word boundary
|
||||
will fail. It won't matter if this increment moves us into the
|
||||
next word. */
|
||||
start_bit += !bi->bits;
|
||||
|
||||
*bit_no = start_bit;
|
||||
}
|
||||
|
||||
/* Advance to the next bit in BI. We don't advance to the next
|
||||
nonzero bit yet. */
|
||||
|
||||
static inline void
|
||||
bmp_iter_next (bitmap_iterator *bi, unsigned *bit_no)
|
||||
{
|
||||
bi->bits >>= 1;
|
||||
*bit_no += 1;
|
||||
}
|
||||
|
||||
/* Advance to the next nonzero bit of a single bitmap, we will have
|
||||
already advanced past the just iterated bit. Return true if there
|
||||
is a bit to iterate. */
|
||||
|
||||
static inline bool
|
||||
bmp_iter_set (bitmap_iterator *bi, unsigned *bit_no)
|
||||
{
|
||||
/* If our current word is nonzero, it contains the bit we want. */
|
||||
if (bi->bits)
|
||||
{
|
||||
next_bit:
|
||||
while (!(bi->bits & 1))
|
||||
{
|
||||
bi->bits >>= 1;
|
||||
*bit_no += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Round up to the word boundary. We might have just iterated past
|
||||
the end of the last word, hence the -1. It is not possible for
|
||||
bit_no to point at the beginning of the now last word. */
|
||||
*bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
|
||||
/ BITMAP_WORD_BITS * BITMAP_WORD_BITS);
|
||||
bi->word_no++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Find the next nonzero word in this elt. */
|
||||
while (bi->word_no != BITMAP_ELEMENT_WORDS)
|
||||
{
|
||||
bi->bits = bi->elt1->bits[bi->word_no];
|
||||
if (bi->bits)
|
||||
goto next_bit;
|
||||
*bit_no += BITMAP_WORD_BITS;
|
||||
bi->word_no++;
|
||||
}
|
||||
|
||||
/* Advance to the next element. */
|
||||
bi->elt1 = bi->elt1->next;
|
||||
if (!bi->elt1)
|
||||
return false;
|
||||
*bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
bi->word_no = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to the next nonzero bit of an intersecting pair of
|
||||
bitmaps. We will have already advanced past the just iterated bit.
|
||||
Return true if there is a bit to iterate. */
|
||||
|
||||
static inline bool
|
||||
bmp_iter_and (bitmap_iterator *bi, unsigned *bit_no)
|
||||
{
|
||||
/* If our current word is nonzero, it contains the bit we want. */
|
||||
if (bi->bits)
|
||||
{
|
||||
next_bit:
|
||||
while (!(bi->bits & 1))
|
||||
{
|
||||
bi->bits >>= 1;
|
||||
*bit_no += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Round up to the word boundary. We might have just iterated past
|
||||
the end of the last word, hence the -1. It is not possible for
|
||||
bit_no to point at the beginning of the now last word. */
|
||||
*bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
|
||||
/ BITMAP_WORD_BITS * BITMAP_WORD_BITS);
|
||||
bi->word_no++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Find the next nonzero word in this elt. */
|
||||
while (bi->word_no != BITMAP_ELEMENT_WORDS)
|
||||
{
|
||||
bi->bits = bi->elt1->bits[bi->word_no] & bi->elt2->bits[bi->word_no];
|
||||
if (bi->bits)
|
||||
goto next_bit;
|
||||
*bit_no += BITMAP_WORD_BITS;
|
||||
bi->word_no++;
|
||||
}
|
||||
|
||||
/* Advance to the next identical element. */
|
||||
do
|
||||
{
|
||||
/* Advance elt1 while it is less than elt2. We always want
|
||||
to advance one elt. */
|
||||
do
|
||||
{
|
||||
bi->elt1 = bi->elt1->next;
|
||||
if (!bi->elt1)
|
||||
return false;
|
||||
}
|
||||
while (bi->elt1->indx < bi->elt2->indx);
|
||||
|
||||
/* Advance elt2 to be no less than elt1. This might not
|
||||
advance. */
|
||||
while (bi->elt2->indx < bi->elt1->indx)
|
||||
{
|
||||
bi->elt2 = bi->elt2->next;
|
||||
if (!bi->elt2)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
while (bi->elt1->indx != bi->elt2->indx);
|
||||
|
||||
*bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
bi->word_no = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to the next nonzero bit in the intersection of
|
||||
complemented bitmaps. We will have already advanced past the just
|
||||
iterated bit. */
|
||||
|
||||
static inline bool
|
||||
bmp_iter_and_compl (bitmap_iterator *bi, unsigned *bit_no)
|
||||
{
|
||||
/* If our current word is nonzero, it contains the bit we want. */
|
||||
if (bi->bits)
|
||||
{
|
||||
next_bit:
|
||||
while (!(bi->bits & 1))
|
||||
{
|
||||
bi->bits >>= 1;
|
||||
*bit_no += 1;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Round up to the word boundary. We might have just iterated past
|
||||
the end of the last word, hence the -1. It is not possible for
|
||||
bit_no to point at the beginning of the now last word. */
|
||||
*bit_no = ((*bit_no + BITMAP_WORD_BITS - 1)
|
||||
/ BITMAP_WORD_BITS * BITMAP_WORD_BITS);
|
||||
bi->word_no++;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Find the next nonzero word in this elt. */
|
||||
while (bi->word_no != BITMAP_ELEMENT_WORDS)
|
||||
{
|
||||
bi->bits = bi->elt1->bits[bi->word_no];
|
||||
if (bi->elt2 && bi->elt2->indx == bi->elt1->indx)
|
||||
bi->bits &= ~bi->elt2->bits[bi->word_no];
|
||||
if (bi->bits)
|
||||
goto next_bit;
|
||||
*bit_no += BITMAP_WORD_BITS;
|
||||
bi->word_no++;
|
||||
}
|
||||
|
||||
/* Advance to the next element of elt1. */
|
||||
bi->elt1 = bi->elt1->next;
|
||||
if (!bi->elt1)
|
||||
return false;
|
||||
|
||||
/* Advance elt2 until it is no less than elt1. */
|
||||
while (bi->elt2 && bi->elt2->indx < bi->elt1->indx)
|
||||
bi->elt2 = bi->elt2->next;
|
||||
|
||||
*bit_no = bi->elt1->indx * BITMAP_ELEMENT_ALL_BITS;
|
||||
bi->word_no = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop over all bits set in BITMAP, starting with MIN and setting
|
||||
BITNUM to the bit number. ITER is a bitmap iterator. BITNUM
|
||||
should be treated as a read-only variable as it contains loop
|
||||
state. */
|
||||
|
||||
#define EXECUTE_IF_SET_IN_BITMAP(BITMAP, MIN, BITNUM, ITER) \
|
||||
for (bmp_iter_set_init (&(ITER), (BITMAP), (MIN), &(BITNUM)); \
|
||||
bmp_iter_set (&(ITER), &(BITNUM)); \
|
||||
bmp_iter_next (&(ITER), &(BITNUM)))
|
||||
|
||||
/* Loop over all the bits set in BITMAP1 & BITMAP2, starting with MIN
|
||||
and setting BITNUM to the bit number. ITER is a bitmap iterator.
|
||||
BITNUM should be treated as a read-only variable as it contains
|
||||
loop state. */
|
||||
|
||||
#define EXECUTE_IF_AND_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \
|
||||
for (bmp_iter_and_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \
|
||||
&(BITNUM)); \
|
||||
bmp_iter_and (&(ITER), &(BITNUM)); \
|
||||
bmp_iter_next (&(ITER), &(BITNUM)))
|
||||
|
||||
/* Loop over all the bits set in BITMAP1 & ~BITMAP2, starting with MIN
|
||||
and setting BITNUM to the bit number. ITER is a bitmap iterator.
|
||||
BITNUM should be treated as a read-only variable as it contains
|
||||
loop state. */
|
||||
|
||||
#define EXECUTE_IF_AND_COMPL_IN_BITMAP(BITMAP1, BITMAP2, MIN, BITNUM, ITER) \
|
||||
for (bmp_iter_and_compl_init (&(ITER), (BITMAP1), (BITMAP2), (MIN), \
|
||||
&(BITNUM)); \
|
||||
bmp_iter_and_compl (&(ITER), &(BITNUM)); \
|
||||
bmp_iter_next (&(ITER), &(BITNUM)))
|
||||
|
||||
#endif /* GCC_BITMAP_H */
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Perform branch target register load optimizations.
|
||||
Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,20 +16,16 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "bitmap.h"
|
||||
#include "sbitmap.h"
|
||||
#include "rtl.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "basic-block.h"
|
||||
#include "regs.h"
|
||||
#include "obstack.h"
|
||||
#include "fibheap.h"
|
||||
#include "output.h"
|
||||
#include "target.h"
|
||||
@ -36,7 +33,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "flags.h"
|
||||
#include "insn-attr.h"
|
||||
#include "function.h"
|
||||
#include "except.h"
|
||||
#include "tm_p.h"
|
||||
#include "toplev.h"
|
||||
#include "tree-pass.h"
|
||||
|
||||
/* Target register optimizations - these are performed after reload. */
|
||||
|
||||
@ -101,6 +101,10 @@ typedef struct btr_def_s
|
||||
as appropriate. */
|
||||
char other_btr_uses_before_def;
|
||||
char other_btr_uses_after_use;
|
||||
/* We set own_end when we have moved a definition into a dominator.
|
||||
Thus, when a later combination removes this definition again, we know
|
||||
to clear out trs_live_at_end again. */
|
||||
char own_end;
|
||||
bitmap live_range;
|
||||
} *btr_def;
|
||||
|
||||
@ -126,9 +130,9 @@ static void link_btr_uses (btr_def *, btr_user *, sbitmap *, sbitmap *, int);
|
||||
static void build_btr_def_use_webs (fibheap_t);
|
||||
static int block_at_edge_of_live_range_p (int, btr_def);
|
||||
static void clear_btr_from_live_range (btr_def def);
|
||||
static void add_btr_to_live_range (btr_def);
|
||||
static void add_btr_to_live_range (btr_def, int);
|
||||
static void augment_live_range (bitmap, HARD_REG_SET *, basic_block,
|
||||
basic_block);
|
||||
basic_block, int);
|
||||
static int choose_btr (HARD_REG_SET);
|
||||
static void combine_btr_defs (btr_def, HARD_REG_SET *);
|
||||
static void btr_def_live_range (btr_def, HARD_REG_SET *);
|
||||
@ -159,6 +163,10 @@ static struct obstack migrate_btrl_obstack;
|
||||
live in that block. */
|
||||
static HARD_REG_SET *btrs_live;
|
||||
|
||||
/* Array indexed by basic block number, giving the set of registers live at
|
||||
the end of that block, including any uses by a final jump insn, if any. */
|
||||
static HARD_REG_SET *btrs_live_at_end;
|
||||
|
||||
/* Set of all target registers that we are willing to allocate. */
|
||||
static HARD_REG_SET all_btrs;
|
||||
|
||||
@ -168,8 +176,7 @@ static int first_btr, last_btr;
|
||||
|
||||
|
||||
|
||||
/* Return an estimate of the frequency of execution of block bb.
|
||||
If we have a profiling count available, we could use it here. */
|
||||
/* Return an estimate of the frequency of execution of block bb. */
|
||||
static int
|
||||
basic_block_freq (basic_block bb)
|
||||
{
|
||||
@ -191,10 +198,10 @@ find_btr_reference (rtx *px, void *preg)
|
||||
if (px == preg)
|
||||
return -1;
|
||||
x = *px;
|
||||
if (GET_CODE (x) != REG)
|
||||
if (!REG_P (x))
|
||||
return 0;
|
||||
regno = REGNO (x);
|
||||
for (i = HARD_REGNO_NREGS (regno, GET_MODE (x)) - 1; i >= 0; i--)
|
||||
for (i = hard_regno_nregs[regno][GET_MODE (x)] - 1; i >= 0; i--)
|
||||
if (TEST_HARD_REG_BIT (all_btrs, regno+i))
|
||||
{
|
||||
btr_reference_found = px;
|
||||
@ -221,7 +228,7 @@ insn_sets_btr_p (rtx insn, int check_const, int *regno)
|
||||
{
|
||||
rtx set;
|
||||
|
||||
if (GET_CODE (insn) == INSN
|
||||
if (NONJUMP_INSN_P (insn)
|
||||
&& (set = single_set (insn)))
|
||||
{
|
||||
rtx dest = SET_DEST (set);
|
||||
@ -230,11 +237,11 @@ insn_sets_btr_p (rtx insn, int check_const, int *regno)
|
||||
if (GET_CODE (dest) == SUBREG)
|
||||
dest = XEXP (dest, 0);
|
||||
|
||||
if (GET_CODE (dest) == REG
|
||||
if (REG_P (dest)
|
||||
&& TEST_HARD_REG_BIT (all_btrs, REGNO (dest)))
|
||||
{
|
||||
if (btr_referenced_p (src, NULL))
|
||||
abort();
|
||||
gcc_assert (!btr_referenced_p (src, NULL));
|
||||
|
||||
if (!check_const || CONSTANT_P (src))
|
||||
{
|
||||
if (regno)
|
||||
@ -315,8 +322,8 @@ add_btr_def (fibheap_t all_btr_defs, basic_block bb, int insn_luid, rtx insn,
|
||||
|
||||
fibheap_insert (all_btr_defs, -this->cost, this);
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Found target reg definition: sets %u { bb %d, insn %d }%s priority %d\n",
|
||||
dest_reg, bb->index, INSN_UID (insn), (this->group ? "" : ":not const"),
|
||||
this->cost);
|
||||
@ -359,13 +366,13 @@ new_btr_user (basic_block bb, int insn_luid, rtx insn)
|
||||
user->n_reaching_defs = 0;
|
||||
user->first_reaching_def = -1;
|
||||
|
||||
if (rtl_dump_file)
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (rtl_dump_file, "Uses target reg: { bb %d, insn %d }",
|
||||
fprintf (dump_file, "Uses target reg: { bb %d, insn %d }",
|
||||
bb->index, INSN_UID (insn));
|
||||
|
||||
if (user->use)
|
||||
fprintf (rtl_dump_file, ": unambiguous use of reg %d\n",
|
||||
fprintf (dump_file, ": unambiguous use of reg %d\n",
|
||||
REGNO (user->use));
|
||||
}
|
||||
|
||||
@ -379,16 +386,16 @@ dump_hard_reg_set (HARD_REG_SET s)
|
||||
int reg;
|
||||
for (reg = 0; reg < FIRST_PSEUDO_REGISTER; reg++)
|
||||
if (TEST_HARD_REG_BIT (s, reg))
|
||||
fprintf (rtl_dump_file, " %d", reg);
|
||||
fprintf (dump_file, " %d", reg);
|
||||
}
|
||||
|
||||
/* Write the set of target regs live in block BB to the dump file. */
|
||||
static void
|
||||
dump_btrs_live (int bb)
|
||||
{
|
||||
fprintf (rtl_dump_file, "BB%d live:", bb);
|
||||
fprintf (dump_file, "BB%d live:", bb);
|
||||
dump_hard_reg_set (btrs_live[bb]);
|
||||
fprintf (rtl_dump_file, "\n");
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
/* REGNO is the number of a branch target register that is being used or
|
||||
@ -423,10 +430,10 @@ note_btr_set (rtx dest, rtx set ATTRIBUTE_UNUSED, void *data)
|
||||
defs_uses_info *info = data;
|
||||
int regno, end_regno;
|
||||
|
||||
if (GET_CODE (dest) != REG)
|
||||
if (!REG_P (dest))
|
||||
return;
|
||||
regno = REGNO (dest);
|
||||
end_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (dest));
|
||||
end_regno = regno + hard_regno_nregs[regno][GET_MODE (dest)];
|
||||
for (; regno < end_regno; regno++)
|
||||
if (TEST_HARD_REG_BIT (all_btrs, regno))
|
||||
{
|
||||
@ -455,13 +462,14 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
defs_uses_info info;
|
||||
|
||||
sbitmap_vector_zero (bb_gen, n_basic_blocks);
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
int reg;
|
||||
btr_def defs_this_bb = NULL;
|
||||
rtx insn;
|
||||
rtx last;
|
||||
int can_throw = 0;
|
||||
|
||||
info.users_this_bb = NULL;
|
||||
info.bb_gen = bb_gen[i];
|
||||
@ -471,7 +479,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
CLEAR_HARD_REG_SET (info.btrs_written_in_block);
|
||||
for (reg = first_btr; reg <= last_btr; reg++)
|
||||
if (TEST_HARD_REG_BIT (all_btrs, reg)
|
||||
&& REGNO_REG_SET_P (bb->global_live_at_start, reg))
|
||||
&& REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, reg))
|
||||
SET_HARD_REG_BIT (info.btrs_live_in_block, reg);
|
||||
|
||||
for (insn = BB_HEAD (bb), last = NEXT_INSN (BB_END (bb));
|
||||
@ -501,6 +509,22 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
SET_BIT (btr_defset[regno - first_btr], insn_uid);
|
||||
note_other_use_this_block (regno, info.users_this_bb);
|
||||
}
|
||||
/* Check for the blockage emitted by expand_nl_goto_receiver. */
|
||||
else if (current_function_has_nonlocal_label
|
||||
&& GET_CODE (PATTERN (insn)) == ASM_INPUT)
|
||||
{
|
||||
btr_user user;
|
||||
|
||||
/* Do the equivalent of calling note_other_use_this_block
|
||||
for every target register. */
|
||||
for (user = info.users_this_bb; user != NULL;
|
||||
user = user->next)
|
||||
if (user->use)
|
||||
user->other_use_this_block = 1;
|
||||
IOR_HARD_REG_SET (info.btrs_written_in_block, all_btrs);
|
||||
IOR_HARD_REG_SET (info.btrs_live_in_block, all_btrs);
|
||||
sbitmap_zero (info.bb_gen);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (btr_referenced_p (PATTERN (insn), NULL))
|
||||
@ -528,7 +552,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
user->next = info.users_this_bb;
|
||||
info.users_this_bb = user;
|
||||
}
|
||||
if (GET_CODE (insn) == CALL_INSN)
|
||||
if (CALL_P (insn))
|
||||
{
|
||||
HARD_REG_SET *clobbered = &call_used_reg_set;
|
||||
HARD_REG_SET call_saved;
|
||||
@ -544,7 +568,7 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
call_used_reg_set);
|
||||
clobbered = &call_saved;
|
||||
}
|
||||
|
||||
|
||||
for (regno = first_btr; regno <= last_btr; regno++)
|
||||
if (TEST_HARD_REG_BIT (*clobbered, regno))
|
||||
note_btr_set (regno_reg_rtx[regno], NULL_RTX, &info);
|
||||
@ -555,7 +579,36 @@ compute_defs_uses_and_gen (fibheap_t all_btr_defs, btr_def *def_array,
|
||||
|
||||
COPY_HARD_REG_SET (btrs_live[i], info.btrs_live_in_block);
|
||||
COPY_HARD_REG_SET (btrs_written[i], info.btrs_written_in_block);
|
||||
if (rtl_dump_file)
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (btrs_live_at_end[i], bb->il.rtl->global_live_at_end);
|
||||
/* If this block ends in a jump insn, add any uses or even clobbers
|
||||
of branch target registers that it might have. */
|
||||
for (insn = BB_END (bb); insn != BB_HEAD (bb) && ! INSN_P (insn); )
|
||||
insn = PREV_INSN (insn);
|
||||
/* ??? for the fall-through edge, it would make sense to insert the
|
||||
btr set on the edge, but that would require to split the block
|
||||
early on so that we can distinguish between dominance from the fall
|
||||
through edge - which can use the call-clobbered registers - from
|
||||
dominance by the throw edge. */
|
||||
if (can_throw_internal (insn))
|
||||
{
|
||||
HARD_REG_SET tmp;
|
||||
|
||||
COPY_HARD_REG_SET (tmp, call_used_reg_set);
|
||||
AND_HARD_REG_SET (tmp, all_btrs);
|
||||
IOR_HARD_REG_SET (btrs_live_at_end[i], tmp);
|
||||
can_throw = 1;
|
||||
}
|
||||
if (can_throw || JUMP_P (insn))
|
||||
{
|
||||
int regno;
|
||||
|
||||
for (regno = first_btr; regno <= last_btr; regno++)
|
||||
if (refers_to_regno_p (regno, regno+1, insn, NULL))
|
||||
SET_HARD_REG_BIT (btrs_live_at_end[i], regno);
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
dump_btrs_live(i);
|
||||
}
|
||||
}
|
||||
@ -570,7 +623,7 @@ compute_kill (sbitmap *bb_kill, sbitmap *btr_defset,
|
||||
/* For each basic block, form the set BB_KILL - the set
|
||||
of definitions that the block kills. */
|
||||
sbitmap_vector_zero (bb_kill, n_basic_blocks);
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
{
|
||||
for (regno = first_btr; regno <= last_btr; regno++)
|
||||
if (TEST_HARD_REG_BIT (all_btrs, regno)
|
||||
@ -593,14 +646,14 @@ compute_out (sbitmap *bb_out, sbitmap *bb_gen, sbitmap *bb_kill, int max_uid)
|
||||
int changed;
|
||||
sbitmap bb_in = sbitmap_alloc (max_uid);
|
||||
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
sbitmap_copy (bb_out[i], bb_gen[i]);
|
||||
|
||||
changed = 1;
|
||||
while (changed)
|
||||
{
|
||||
changed = 0;
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
{
|
||||
sbitmap_union_of_preds (bb_in, bb_out, i);
|
||||
changed |= sbitmap_union_of_diff_cg (bb_out[i], bb_gen[i],
|
||||
@ -619,7 +672,7 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
|
||||
|
||||
/* Link uses to the uses lists of all of their reaching defs.
|
||||
Count up the number of reaching defs of each use. */
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
rtx insn;
|
||||
@ -649,7 +702,8 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
|
||||
{
|
||||
/* Find all the reaching defs for this use. */
|
||||
sbitmap reaching_defs_of_reg = sbitmap_alloc(max_uid);
|
||||
int uid;
|
||||
unsigned int uid = 0;
|
||||
sbitmap_iterator sbi;
|
||||
|
||||
if (user->use)
|
||||
sbitmap_a_and_b (
|
||||
@ -670,14 +724,14 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
|
||||
reaching_defs,
|
||||
btr_defset[reg - first_btr]);
|
||||
}
|
||||
EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid,
|
||||
EXECUTE_IF_SET_IN_SBITMAP (reaching_defs_of_reg, 0, uid, sbi)
|
||||
{
|
||||
btr_def def = def_array[uid];
|
||||
|
||||
/* We now know that def reaches user. */
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Def in insn %d reaches use in insn %d\n",
|
||||
uid, insn_uid);
|
||||
|
||||
@ -691,8 +745,8 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
|
||||
def->has_ambiguous_use = 1;
|
||||
def_array[user->first_reaching_def]
|
||||
->has_ambiguous_use = 1;
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"(use %d has multiple reaching defs)\n",
|
||||
insn_uid);
|
||||
}
|
||||
@ -702,11 +756,11 @@ link_btr_uses (btr_def *def_array, btr_user *use_array, sbitmap *bb_out,
|
||||
def->other_btr_uses_after_use = 1;
|
||||
user->next = def->uses;
|
||||
def->uses = user;
|
||||
});
|
||||
}
|
||||
sbitmap_free (reaching_defs_of_reg);
|
||||
}
|
||||
|
||||
if (GET_CODE (insn) == CALL_INSN)
|
||||
if (CALL_P (insn))
|
||||
{
|
||||
int regno;
|
||||
|
||||
@ -726,12 +780,12 @@ static void
|
||||
build_btr_def_use_webs (fibheap_t all_btr_defs)
|
||||
{
|
||||
const int max_uid = get_max_uid ();
|
||||
btr_def *def_array = xcalloc (max_uid, sizeof (btr_def));
|
||||
btr_user *use_array = xcalloc (max_uid, sizeof (btr_user));
|
||||
btr_def *def_array = XCNEWVEC (btr_def, max_uid);
|
||||
btr_user *use_array = XCNEWVEC (btr_user, max_uid);
|
||||
sbitmap *btr_defset = sbitmap_vector_alloc (
|
||||
(last_btr - first_btr) + 1, max_uid);
|
||||
sbitmap *bb_gen = sbitmap_vector_alloc (n_basic_blocks, max_uid);
|
||||
HARD_REG_SET *btrs_written = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
|
||||
HARD_REG_SET *btrs_written = XCNEWVEC (HARD_REG_SET, n_basic_blocks);
|
||||
sbitmap *bb_kill;
|
||||
sbitmap *bb_out;
|
||||
|
||||
@ -787,37 +841,49 @@ block_at_edge_of_live_range_p (int bb, btr_def def)
|
||||
static void
|
||||
clear_btr_from_live_range (btr_def def)
|
||||
{
|
||||
int bb;
|
||||
unsigned bb;
|
||||
bitmap_iterator bi;
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP
|
||||
(def->live_range, 0, bb,
|
||||
{
|
||||
if ((!def->other_btr_uses_before_def
|
||||
&& !def->other_btr_uses_after_use)
|
||||
|| !block_at_edge_of_live_range_p (bb, def))
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (btrs_live[bb], def->btr);
|
||||
if (rtl_dump_file)
|
||||
dump_btrs_live (bb);
|
||||
}
|
||||
});
|
||||
EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
|
||||
{
|
||||
if ((!def->other_btr_uses_before_def
|
||||
&& !def->other_btr_uses_after_use)
|
||||
|| !block_at_edge_of_live_range_p (bb, def))
|
||||
{
|
||||
CLEAR_HARD_REG_BIT (btrs_live[bb], def->btr);
|
||||
CLEAR_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
|
||||
if (dump_file)
|
||||
dump_btrs_live (bb);
|
||||
}
|
||||
}
|
||||
if (def->own_end)
|
||||
CLEAR_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
|
||||
}
|
||||
|
||||
|
||||
/* We are adding the def/use web DEF. Add the target register used
|
||||
in this web to the live set of all of the basic blocks that contain
|
||||
the live range of the web. */
|
||||
the live range of the web.
|
||||
If OWN_END is set, also show that the register is live from our
|
||||
definitions at the end of the basic block where it is defined. */
|
||||
static void
|
||||
add_btr_to_live_range (btr_def def)
|
||||
add_btr_to_live_range (btr_def def, int own_end)
|
||||
{
|
||||
int bb;
|
||||
EXECUTE_IF_SET_IN_BITMAP
|
||||
(def->live_range, 0, bb,
|
||||
{
|
||||
SET_HARD_REG_BIT (btrs_live[bb], def->btr);
|
||||
if (rtl_dump_file)
|
||||
dump_btrs_live (bb);
|
||||
});
|
||||
unsigned bb;
|
||||
bitmap_iterator bi;
|
||||
|
||||
EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
|
||||
{
|
||||
SET_HARD_REG_BIT (btrs_live[bb], def->btr);
|
||||
SET_HARD_REG_BIT (btrs_live_at_end[bb], def->btr);
|
||||
if (dump_file)
|
||||
dump_btrs_live (bb);
|
||||
}
|
||||
if (own_end)
|
||||
{
|
||||
SET_HARD_REG_BIT (btrs_live_at_end[def->bb->index], def->btr);
|
||||
def->own_end = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update a live range to contain the basic block NEW_BLOCK, and all
|
||||
@ -826,39 +892,59 @@ add_btr_to_live_range (btr_def def)
|
||||
all other blocks in the existing live range.
|
||||
Also add to the set BTRS_LIVE_IN_RANGE all target registers that
|
||||
are live in the blocks that we add to the live range.
|
||||
If FULL_RANGE is set, include the full live range of NEW_BB;
|
||||
otherwise, if NEW_BB dominates HEAD_BB, only add registers that
|
||||
are life at the end of NEW_BB for NEW_BB itself.
|
||||
It is a precondition that either NEW_BLOCK dominates HEAD,or
|
||||
HEAD dom NEW_BLOCK. This is used to speed up the
|
||||
implementation of this function. */
|
||||
static void
|
||||
augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range,
|
||||
basic_block head_bb, basic_block new_bb)
|
||||
basic_block head_bb, basic_block new_bb, int full_range)
|
||||
{
|
||||
basic_block *worklist, *tos;
|
||||
|
||||
tos = worklist = xmalloc (sizeof (basic_block) * (n_basic_blocks + 1));
|
||||
tos = worklist = XNEWVEC (basic_block, n_basic_blocks + 1);
|
||||
|
||||
if (dominated_by_p (CDI_DOMINATORS, new_bb, head_bb))
|
||||
*tos++ = new_bb;
|
||||
else if (dominated_by_p (CDI_DOMINATORS, head_bb, new_bb))
|
||||
{
|
||||
edge e;
|
||||
int new_block = new_bb->index;
|
||||
|
||||
bitmap_set_bit (live_range, new_block);
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]);
|
||||
if (rtl_dump_file)
|
||||
if (new_bb == head_bb)
|
||||
{
|
||||
fprintf (rtl_dump_file,
|
||||
"Adding block %d to live range\n", new_block);
|
||||
fprintf (rtl_dump_file,"Now live btrs are ");
|
||||
dump_hard_reg_set (*btrs_live_in_range);
|
||||
fprintf (rtl_dump_file, "\n");
|
||||
if (full_range)
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_bb->index]);
|
||||
free (tos);
|
||||
return;
|
||||
}
|
||||
for (e = head_bb->pred; e; e = e->pred_next)
|
||||
*tos++ = e->src;
|
||||
*tos++ = new_bb;
|
||||
}
|
||||
else
|
||||
abort();
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
int new_block = new_bb->index;
|
||||
|
||||
gcc_assert (dominated_by_p (CDI_DOMINATORS, head_bb, new_bb));
|
||||
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[head_bb->index]);
|
||||
bitmap_set_bit (live_range, new_block);
|
||||
/* A previous btr migration could have caused a register to be
|
||||
live just at the end of new_block which we need in full, so
|
||||
use trs_live_at_end even if full_range is set. */
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live_at_end[new_block]);
|
||||
if (full_range)
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range, btrs_live[new_block]);
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (dump_file,
|
||||
"Adding end of block %d and rest of %d to live range\n",
|
||||
new_block, head_bb->index);
|
||||
fprintf (dump_file,"Now live btrs are ");
|
||||
dump_hard_reg_set (*btrs_live_in_range);
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
FOR_EACH_EDGE (e, ei, head_bb->preds)
|
||||
*tos++ = e->src;
|
||||
}
|
||||
|
||||
while (tos != worklist)
|
||||
{
|
||||
@ -866,20 +952,25 @@ augment_live_range (bitmap live_range, HARD_REG_SET *btrs_live_in_range,
|
||||
if (!bitmap_bit_p (live_range, bb->index))
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
bitmap_set_bit (live_range, bb->index);
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range,
|
||||
btrs_live[bb->index]);
|
||||
if (rtl_dump_file)
|
||||
/* A previous btr migration could have caused a register to be
|
||||
live just at the end of a block which we need in full. */
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range,
|
||||
btrs_live_at_end[bb->index]);
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (rtl_dump_file,
|
||||
fprintf (dump_file,
|
||||
"Adding block %d to live range\n", bb->index);
|
||||
fprintf (rtl_dump_file,"Now live btrs are ");
|
||||
fprintf (dump_file,"Now live btrs are ");
|
||||
dump_hard_reg_set (*btrs_live_in_range);
|
||||
fprintf (rtl_dump_file, "\n");
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
for (e = bb->pred; e != NULL; e = e->pred_next)
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
{
|
||||
basic_block pred = e->src;
|
||||
if (!bitmap_bit_p (live_range, pred->index))
|
||||
@ -926,14 +1017,19 @@ btr_def_live_range (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
{
|
||||
btr_user user;
|
||||
|
||||
def->live_range = BITMAP_XMALLOC ();
|
||||
def->live_range = BITMAP_ALLOC (NULL);
|
||||
|
||||
bitmap_set_bit (def->live_range, def->bb->index);
|
||||
COPY_HARD_REG_SET (*btrs_live_in_range, btrs_live[def->bb->index]);
|
||||
COPY_HARD_REG_SET (*btrs_live_in_range,
|
||||
(flag_btr_bb_exclusive
|
||||
? btrs_live : btrs_live_at_end)[def->bb->index]);
|
||||
|
||||
for (user = def->uses; user != NULL; user = user->next)
|
||||
augment_live_range (def->live_range, btrs_live_in_range,
|
||||
def->bb, user->bb);
|
||||
def->bb, user->bb,
|
||||
(flag_btr_bb_exclusive
|
||||
|| user->insn != BB_END (def->bb)
|
||||
|| !JUMP_P (user->insn)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -941,15 +1037,17 @@ btr_def_live_range (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
the set of target registers live over it, because migration
|
||||
of other PT instructions may have affected it.
|
||||
*/
|
||||
int bb;
|
||||
unsigned bb;
|
||||
unsigned def_bb = flag_btr_bb_exclusive ? -1 : def->bb->index;
|
||||
bitmap_iterator bi;
|
||||
|
||||
CLEAR_HARD_REG_SET (*btrs_live_in_range);
|
||||
EXECUTE_IF_SET_IN_BITMAP
|
||||
(def->live_range, 0, bb,
|
||||
{
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range,
|
||||
btrs_live[bb]);
|
||||
});
|
||||
EXECUTE_IF_SET_IN_BITMAP (def->live_range, 0, bb, bi)
|
||||
{
|
||||
IOR_HARD_REG_SET (*btrs_live_in_range,
|
||||
(def_bb == bb
|
||||
? btrs_live_at_end : btrs_live) [bb]);
|
||||
}
|
||||
}
|
||||
if (!def->other_btr_uses_before_def &&
|
||||
!def->other_btr_uses_after_use)
|
||||
@ -979,7 +1077,7 @@ combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
target registers live over the merged range. */
|
||||
int btr;
|
||||
HARD_REG_SET combined_btrs_live;
|
||||
bitmap combined_live_range = BITMAP_XMALLOC ();
|
||||
bitmap combined_live_range = BITMAP_ALLOC (NULL);
|
||||
btr_user user;
|
||||
|
||||
if (other_def->live_range == NULL)
|
||||
@ -992,14 +1090,17 @@ combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
|
||||
for (user = other_def->uses; user != NULL; user = user->next)
|
||||
augment_live_range (combined_live_range, &combined_btrs_live,
|
||||
def->bb, user->bb);
|
||||
def->bb, user->bb,
|
||||
(flag_btr_bb_exclusive
|
||||
|| user->insn != BB_END (def->bb)
|
||||
|| !JUMP_P (user->insn)));
|
||||
|
||||
btr = choose_btr (combined_btrs_live);
|
||||
if (btr != -1)
|
||||
{
|
||||
/* We can combine them. */
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Combining def in insn %d with def in insn %d\n",
|
||||
INSN_UID (other_def->insn), INSN_UID (def->insn));
|
||||
|
||||
@ -1026,7 +1127,7 @@ combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
clear_btr_from_live_range (other_def);
|
||||
other_def->uses = NULL;
|
||||
bitmap_copy (def->live_range, combined_live_range);
|
||||
if (other_def->other_btr_uses_after_use)
|
||||
if (other_def->btr == btr && other_def->other_btr_uses_after_use)
|
||||
def->other_btr_uses_after_use = 1;
|
||||
COPY_HARD_REG_SET (*btrs_live_in_range, combined_btrs_live);
|
||||
|
||||
@ -1034,7 +1135,7 @@ combine_btr_defs (btr_def def, HARD_REG_SET *btrs_live_in_range)
|
||||
delete_insn (other_def->insn);
|
||||
|
||||
}
|
||||
BITMAP_XFREE (combined_live_range);
|
||||
BITMAP_FREE (combined_live_range);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1064,8 +1165,8 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range,
|
||||
btr_user user;
|
||||
rtx set;
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf(rtl_dump_file, "migrating to basic block %d, using reg %d\n",
|
||||
if (dump_file)
|
||||
fprintf(dump_file, "migrating to basic block %d, using reg %d\n",
|
||||
new_def_bb->index, btr);
|
||||
|
||||
clear_btr_from_live_range (def);
|
||||
@ -1073,22 +1174,33 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range,
|
||||
def->bb = new_def_bb;
|
||||
def->luid = 0;
|
||||
def->cost = basic_block_freq (new_def_bb);
|
||||
def->other_btr_uses_before_def = 0;
|
||||
bitmap_copy (def->live_range, live_range);
|
||||
combine_btr_defs (def, btrs_live_in_range);
|
||||
btr = def->btr;
|
||||
add_btr_to_live_range (def);
|
||||
if (GET_CODE (insp) == CODE_LABEL)
|
||||
def->other_btr_uses_before_def
|
||||
= TEST_HARD_REG_BIT (btrs_live[b->index], btr) ? 1 : 0;
|
||||
add_btr_to_live_range (def, 1);
|
||||
if (LABEL_P (insp))
|
||||
insp = NEXT_INSN (insp);
|
||||
/* N.B.: insp is expected to be NOTE_INSN_BASIC_BLOCK now. Some
|
||||
optimizations can result in insp being both first and last insn of
|
||||
its basic block. */
|
||||
/* ?? some assertions to check that insp is sensible? */
|
||||
|
||||
if (def->other_btr_uses_before_def)
|
||||
{
|
||||
insp = BB_END (b);
|
||||
for (insp = BB_END (b); ! INSN_P (insp); insp = PREV_INSN (insp))
|
||||
gcc_assert (insp != BB_HEAD (b));
|
||||
|
||||
if (JUMP_P (insp) || can_throw_internal (insp))
|
||||
insp = PREV_INSN (insp);
|
||||
}
|
||||
|
||||
set = single_set (old_insn);
|
||||
src = SET_SRC (set);
|
||||
btr_mode = GET_MODE (SET_DEST (set));
|
||||
btr_rtx = gen_rtx (REG, btr_mode, btr);
|
||||
btr_rtx = gen_rtx_REG (btr_mode, btr);
|
||||
|
||||
new_insn = gen_move_insn (btr_rtx, src);
|
||||
|
||||
@ -1097,8 +1209,8 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range,
|
||||
|
||||
regs_ever_live[btr] = 1;
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "New pt is insn %d, inserted after insn %d\n",
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "New pt is insn %d, inserted after insn %d\n",
|
||||
INSN_UID (def->insn), INSN_UID (insp));
|
||||
|
||||
/* Delete the old target register initialization. */
|
||||
@ -1117,7 +1229,7 @@ move_btr_def (basic_block new_def_bb, int btr, btr_def def, bitmap live_range,
|
||||
|| GET_MODE (user->use) == VOIDmode)
|
||||
replacement_rtx = btr_rtx;
|
||||
else
|
||||
replacement_rtx = gen_rtx (REG, GET_MODE (user->use), btr);
|
||||
replacement_rtx = gen_rtx_REG (GET_MODE (user->use), btr);
|
||||
replace_rtx (user->insn, user->use, replacement_rtx);
|
||||
user->use = replacement_rtx;
|
||||
}
|
||||
@ -1170,18 +1282,18 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
int give_up = 0;
|
||||
int def_moved = 0;
|
||||
btr_user user;
|
||||
int def_latency = 1;
|
||||
int def_latency;
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"Attempting to migrate pt from insn %d (cost = %d, min_cost = %d) ... ",
|
||||
INSN_UID (def->insn), def->cost, min_cost);
|
||||
|
||||
if (!def->group || def->has_ambiguous_use)
|
||||
/* These defs are not migratable. */
|
||||
{
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "it's not migratable\n");
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "it's not migratable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1190,24 +1302,21 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
no need to consider it further.
|
||||
*/
|
||||
{
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "it's already combined with another pt\n");
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "it's already combined with another pt\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
btr_def_live_range (def, &btrs_live_in_range);
|
||||
live_range = BITMAP_XMALLOC ();
|
||||
live_range = BITMAP_ALLOC (NULL);
|
||||
bitmap_copy (live_range, def->live_range);
|
||||
|
||||
#ifdef INSN_SCHEDULING
|
||||
if ((*targetm.sched.use_dfa_pipeline_interface) ())
|
||||
def_latency = insn_default_latency (def->insn);
|
||||
else
|
||||
def_latency = result_ready_cost (def->insn);
|
||||
def_latency = insn_default_latency (def->insn) * issue_rate;
|
||||
#else
|
||||
def_latency = issue_rate;
|
||||
#endif
|
||||
|
||||
def_latency *= issue_rate;
|
||||
|
||||
for (user = def->uses; user != NULL; user = user->next)
|
||||
{
|
||||
if (user->bb == def->bb
|
||||
@ -1230,20 +1339,30 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
/* Try to move the instruction that sets the target register into
|
||||
basic block TRY. */
|
||||
int try_freq = basic_block_freq (try);
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "trying block %d ...", try->index);
|
||||
/* If TRY has abnormal edges, skip it. */
|
||||
FOR_EACH_EDGE (e, ei, try->succs)
|
||||
if (e->flags & EDGE_COMPLEX)
|
||||
break;
|
||||
if (e)
|
||||
continue;
|
||||
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "trying block %d ...", try->index);
|
||||
|
||||
if (try_freq < def_basic_block_freq
|
||||
|| (try_freq == def_basic_block_freq && btr_used_near_def))
|
||||
{
|
||||
int btr;
|
||||
augment_live_range (live_range, &btrs_live_in_range, def->bb, try);
|
||||
if (rtl_dump_file)
|
||||
augment_live_range (live_range, &btrs_live_in_range, def->bb, try,
|
||||
flag_btr_bb_exclusive);
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (rtl_dump_file, "Now btrs live in range are: ");
|
||||
fprintf (dump_file, "Now btrs live in range are: ");
|
||||
dump_hard_reg_set (btrs_live_in_range);
|
||||
fprintf (rtl_dump_file, "\n");
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
btr = choose_btr (btrs_live_in_range);
|
||||
if (btr != -1)
|
||||
@ -1259,8 +1378,8 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
/* There are no free target registers available to move
|
||||
this far forward, so give up */
|
||||
give_up = 1;
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file,
|
||||
if (dump_file)
|
||||
fprintf (dump_file,
|
||||
"giving up because there are no free target registers\n");
|
||||
}
|
||||
|
||||
@ -1269,10 +1388,10 @@ migrate_btr_def (btr_def def, int min_cost)
|
||||
if (!def_moved)
|
||||
{
|
||||
give_up = 1;
|
||||
if (rtl_dump_file)
|
||||
fprintf (rtl_dump_file, "failed to move\n");
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "failed to move\n");
|
||||
}
|
||||
BITMAP_XFREE (live_range);
|
||||
BITMAP_FREE (live_range);
|
||||
return !give_up;
|
||||
}
|
||||
|
||||
@ -1285,14 +1404,14 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
|
||||
int reg;
|
||||
|
||||
gcc_obstack_init (&migrate_btrl_obstack);
|
||||
if (rtl_dump_file)
|
||||
if (dump_file)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
for (i = NUM_FIXED_BLOCKS; i < n_basic_blocks; i++)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK (i);
|
||||
fprintf(rtl_dump_file,
|
||||
fprintf(dump_file,
|
||||
"Basic block %d: count = " HOST_WIDEST_INT_PRINT_DEC
|
||||
" loop-depth = %d idom = %d\n",
|
||||
i, (HOST_WIDEST_INT) bb->count, bb->loop_depth,
|
||||
@ -1312,45 +1431,43 @@ migrate_btr_defs (enum reg_class btr_class, int allow_callee_save)
|
||||
}
|
||||
|
||||
btrs_live = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
|
||||
btrs_live_at_end = xcalloc (n_basic_blocks, sizeof (HARD_REG_SET));
|
||||
|
||||
build_btr_def_use_webs (all_btr_defs);
|
||||
|
||||
while (!fibheap_empty (all_btr_defs))
|
||||
{
|
||||
btr_def def =
|
||||
(btr_def) fibheap_extract_min (all_btr_defs);
|
||||
btr_def def = fibheap_extract_min (all_btr_defs);
|
||||
int min_cost = -fibheap_min_key (all_btr_defs);
|
||||
if (migrate_btr_def (def, min_cost))
|
||||
{
|
||||
fibheap_insert (all_btr_defs, -def->cost, (void *) def);
|
||||
if (rtl_dump_file)
|
||||
if (dump_file)
|
||||
{
|
||||
fprintf (rtl_dump_file,
|
||||
fprintf (dump_file,
|
||||
"Putting insn %d back on queue with priority %d\n",
|
||||
INSN_UID (def->insn), def->cost);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (def->live_range)
|
||||
BITMAP_XFREE (def->live_range);
|
||||
}
|
||||
BITMAP_FREE (def->live_range);
|
||||
}
|
||||
|
||||
free (btrs_live);
|
||||
free (btrs_live_at_end);
|
||||
obstack_free (&migrate_btrl_obstack, NULL);
|
||||
fibheap_delete (all_btr_defs);
|
||||
}
|
||||
|
||||
void
|
||||
branch_target_load_optimize (rtx insns, bool after_prologue_epilogue_gen)
|
||||
branch_target_load_optimize (bool after_prologue_epilogue_gen)
|
||||
{
|
||||
enum reg_class class = (*targetm.branch_target_register_class) ();
|
||||
enum reg_class class = targetm.branch_target_register_class ();
|
||||
if (class != NO_REGS)
|
||||
{
|
||||
/* Initialize issue_rate. */
|
||||
if (targetm.sched.issue_rate)
|
||||
issue_rate = (*targetm.sched.issue_rate) ();
|
||||
issue_rate = targetm.sched.issue_rate ();
|
||||
else
|
||||
issue_rate = 1;
|
||||
|
||||
@ -1361,12 +1478,12 @@ branch_target_load_optimize (rtx insns, bool after_prologue_epilogue_gen)
|
||||
cleanup_cfg (optimize ? CLEANUP_EXPENSIVE : 0);
|
||||
#endif
|
||||
|
||||
life_analysis (insns, NULL, 0);
|
||||
life_analysis (0);
|
||||
|
||||
/* Dominator info is also needed for migrate_btr_def. */
|
||||
calculate_dominance_info (CDI_DOMINATORS);
|
||||
migrate_btr_defs (class,
|
||||
((*targetm.branch_target_register_callee_saved)
|
||||
(targetm.branch_target_register_callee_saved
|
||||
(after_prologue_epilogue_gen)));
|
||||
|
||||
free_dominance_info (CDI_DOMINATORS);
|
||||
@ -1375,3 +1492,51 @@ branch_target_load_optimize (rtx insns, bool after_prologue_epilogue_gen)
|
||||
PROP_DEATH_NOTES | PROP_REG_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
gate_handle_branch_target_load_optimize (void)
|
||||
{
|
||||
return (optimize > 0 && flag_branch_target_load_optimize2);
|
||||
}
|
||||
|
||||
|
||||
static unsigned int
|
||||
rest_of_handle_branch_target_load_optimize (void)
|
||||
{
|
||||
static int warned = 0;
|
||||
|
||||
/* Leave this a warning for now so that it is possible to experiment
|
||||
with running this pass twice. In 3.6, we should either make this
|
||||
an error, or use separate dump files. */
|
||||
if (flag_branch_target_load_optimize
|
||||
&& flag_branch_target_load_optimize2
|
||||
&& !warned)
|
||||
{
|
||||
warning (0, "branch target register load optimization is not intended "
|
||||
"to be run twice");
|
||||
|
||||
warned = 1;
|
||||
}
|
||||
|
||||
branch_target_load_optimize (epilogue_completed);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct tree_opt_pass pass_branch_target_load_optimize =
|
||||
{
|
||||
"btl", /* name */
|
||||
gate_handle_branch_target_load_optimize, /* gate */
|
||||
rest_of_handle_branch_target_load_optimize, /* execute */
|
||||
NULL, /* sub */
|
||||
NULL, /* next */
|
||||
0, /* static_pass_number */
|
||||
0, /* tv_id */
|
||||
0, /* properties_required */
|
||||
0, /* properties_provided */
|
||||
0, /* properties_destroyed */
|
||||
0, /* todo_flags_start */
|
||||
TODO_dump_func |
|
||||
TODO_ggc_collect, /* todo_flags_finish */
|
||||
'd' /* letter */
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Joseph Myers <jsm28@cam.ac.uk>.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -15,8 +15,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* This header provides a declarative way of describing the attributes
|
||||
that are applied to some functions by default.
|
||||
@ -55,6 +55,8 @@ DEF_ATTR_FOR_INT (1)
|
||||
DEF_ATTR_FOR_INT (2)
|
||||
DEF_ATTR_FOR_INT (3)
|
||||
DEF_ATTR_FOR_INT (4)
|
||||
DEF_ATTR_FOR_INT (5)
|
||||
DEF_ATTR_FOR_INT (6)
|
||||
#undef DEF_ATTR_FOR_INT
|
||||
|
||||
/* Construct a tree for a list of two integers. */
|
||||
@ -67,9 +69,13 @@ DEF_LIST_INT_INT (2,0)
|
||||
DEF_LIST_INT_INT (2,3)
|
||||
DEF_LIST_INT_INT (3,0)
|
||||
DEF_LIST_INT_INT (3,4)
|
||||
DEF_LIST_INT_INT (4,0)
|
||||
DEF_LIST_INT_INT (4,5)
|
||||
DEF_LIST_INT_INT (5,0)
|
||||
DEF_LIST_INT_INT (5,6)
|
||||
#undef DEF_LIST_INT_INT
|
||||
|
||||
/* Construct tress for identifiers. */
|
||||
/* Construct trees for identifiers. */
|
||||
DEF_ATTR_IDENT (ATTR_CONST, "const")
|
||||
DEF_ATTR_IDENT (ATTR_FORMAT, "format")
|
||||
DEF_ATTR_IDENT (ATTR_FORMAT_ARG, "format_arg")
|
||||
@ -83,45 +89,65 @@ DEF_ATTR_IDENT (ATTR_GCC_DIAG, "gcc_diag")
|
||||
DEF_ATTR_IDENT (ATTR_GCC_CDIAG, "gcc_cdiag")
|
||||
DEF_ATTR_IDENT (ATTR_GCC_CXXDIAG, "gcc_cxxdiag")
|
||||
DEF_ATTR_IDENT (ATTR_PURE, "pure")
|
||||
DEF_ATTR_IDENT (ATTR_NOVOPS, "no vops")
|
||||
DEF_ATTR_IDENT (ATTR_SCANF, "scanf")
|
||||
DEF_ATTR_IDENT (ATTR_SENTINEL, "sentinel")
|
||||
DEF_ATTR_IDENT (ATTR_STRFMON, "strfmon")
|
||||
DEF_ATTR_IDENT (ATTR_STRFTIME, "strftime")
|
||||
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOVOPS_LIST, ATTR_NOVOPS, ATTR_NULL, ATTR_NULL)
|
||||
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_LIST, ATTR_NOTHROW, ATTR_NULL, ATTR_NULL)
|
||||
|
||||
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_LIST, ATTR_CONST, \
|
||||
ATTR_NULL, ATTR_NOTHROW_LIST)
|
||||
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_LIST, ATTR_PURE, \
|
||||
ATTR_NULL, ATTR_NOTHROW_LIST)
|
||||
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NOVOPS_LIST, ATTR_NOVOPS, \
|
||||
ATTR_NULL, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_ATTR_TREE_LIST (ATTR_NORETURN_NOTHROW_LIST, ATTR_NORETURN, \
|
||||
ATTR_NULL, ATTR_NOTHROW_LIST)
|
||||
DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_LIST, ATTR_MALLOC, \
|
||||
ATTR_NULL, ATTR_NOTHROW_LIST)
|
||||
DEF_ATTR_TREE_LIST (ATTR_SENTINEL_NOTHROW_LIST, ATTR_SENTINEL, \
|
||||
ATTR_NULL, ATTR_NOTHROW_LIST)
|
||||
|
||||
/* Functions whose pointer parameter(s) are all nonnull. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NONNULL_LIST, ATTR_NONNULL, ATTR_NULL, ATTR_NULL)
|
||||
/* Functions whose first parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, ATTR_NULL)
|
||||
/* Functions whose second parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, ATTR_NULL)
|
||||
/* Nothrow functions with the sentinel(1) attribute. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_SENTINEL_1, ATTR_SENTINEL, ATTR_LIST_1, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose pointer parameter(s) are all nonnull. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL, ATTR_NONNULL, ATTR_NULL, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose first parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1, ATTR_NONNULL, ATTR_LIST_1, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose second parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_2, ATTR_NONNULL, ATTR_LIST_2, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose third parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_3, ATTR_NONNULL, ATTR_LIST_3, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose first and second parameters are nonnull pointers. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_2, ATTR_NONNULL, ATTR_LIST_2, \
|
||||
ATTR_NOTHROW_NONNULL_1)
|
||||
/* Nothrow functions whose first and fourth parameters are nonnull pointers. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_1_4, ATTR_NONNULL, ATTR_LIST_4, \
|
||||
ATTR_NOTHROW_NONNULL_1)
|
||||
/* Nothrow const functions whose first parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL_1, ATTR_CONST, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL_1)
|
||||
/* Nothrow pure functions whose first parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_1, ATTR_PURE, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL_1)
|
||||
/* Nothrow pure functions whose first and second parameters are nonnull pointers. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL_1_2, ATTR_PURE, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL_1_2)
|
||||
/* Nothrow malloc functions whose first parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_NONNULL_1, ATTR_MALLOC, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL_1)
|
||||
/* Nothrow functions whose fourth parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_4, ATTR_NONNULL, ATTR_LIST_4, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow functions whose fifth parameter is a nonnull pointer. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_NOTHROW_NONNULL_5, ATTR_NONNULL, ATTR_LIST_5, \
|
||||
ATTR_NOTHROW_LIST)
|
||||
/* Nothrow const functions whose pointer parameter(s) are all nonnull. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_CONST_NOTHROW_NONNULL, ATTR_CONST, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL)
|
||||
/* Nothrow pure functions whose pointer parameter(s) are all nonnull. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_PURE_NOTHROW_NONNULL, ATTR_PURE, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL)
|
||||
/* Nothrow malloc functions whose pointer parameter(s) are all nonnull. */
|
||||
DEF_ATTR_TREE_LIST (ATTR_MALLOC_NOTHROW_NONNULL, ATTR_MALLOC, ATTR_NULL, \
|
||||
ATTR_NOTHROW_NONNULL)
|
||||
|
||||
/* Construct a tree for a format attribute. */
|
||||
#define DEF_FORMAT_ATTRIBUTE(TYPE, FA, VALUES) \
|
||||
@ -135,6 +161,10 @@ DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_0)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,2,2_3)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_0)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,3,3_4)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,4,4_0)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,4,4_5)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,5,5_0)
|
||||
DEF_FORMAT_ATTRIBUTE(PRINTF,5,5_6)
|
||||
DEF_FORMAT_ATTRIBUTE(SCANF,1,1_0)
|
||||
DEF_FORMAT_ATTRIBUTE(SCANF,1,1_2)
|
||||
DEF_FORMAT_ATTRIBUTE(SCANF,2,2_0)
|
||||
|
@ -1,4 +1,5 @@
|
||||
/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -14,10 +15,10 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* This header provides a declaritive way of describing the types that
|
||||
/* This header provides a declarative way of describing the types that
|
||||
are used when declaring builtin functions.
|
||||
|
||||
Before including this header, you must define the following macros:
|
||||
@ -32,6 +33,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
DEF_FUNCTION_TYPE_2 (ENUM, RETURN, ARG1, ARG2)
|
||||
DEF_FUNCTION_TYPE_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
|
||||
DEF_FUNCTION_TYPE_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)
|
||||
DEF_FUNCTION_TYPE_5 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
|
||||
DEF_FUNCTION_TYPE_6 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6)
|
||||
DEF_FUNCTION_TYPE_7 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7)
|
||||
|
||||
These macros describe function types. ENUM is as above. The
|
||||
RETURN type is one of the enumerals already defined. ARG1, ARG2,
|
||||
@ -41,6 +45,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
DEF_FUNCTION_TYPE_VAR_1 (ENUM, RETURN, ARG1)
|
||||
DEF_FUNCTION_TYPE_VAR_2 (ENUM, RETURN, ARG1, ARG2)
|
||||
DEF_FUNCTION_TYPE_VAR_3 (ENUM, RETURN, ARG1, ARG2, ARG3)
|
||||
DEF_FUNCTION_TYPE_VAR_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)
|
||||
DEF_FUNCTION_TYPE_VAR_4 (ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)
|
||||
|
||||
Similar, but for function types that take variable arguments.
|
||||
For example:
|
||||
@ -53,20 +59,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
DEF_FUNCTION_TYPE_VAR_1 (BT_INT_DOUBLE_VAR, BT_INT, BT_DOUBLE)
|
||||
|
||||
describes the type `int ()(double, ...)'.
|
||||
|
||||
|
||||
DEF_POINTER_TYPE (ENUM, TYPE)
|
||||
|
||||
This macro describes a pointer type. ENUM is as above; TYPE is
|
||||
the type pointed to. */
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_VOID, void_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_BOOL, boolean_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_INT, integer_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UNSIGNED, unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINT, unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONG, long_integer_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_ULONG, long_unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONGLONG, long_long_integer_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_ULONGLONG, long_long_unsigned_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_UINTMAX, uintmax_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_WORD, (*lang_hooks.types.type_for_mode) (word_mode, 0))
|
||||
DEF_PRIMITIVE_TYPE (BT_FLOAT, float_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_INTMAX, intmax_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DOUBLE, double_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE, long_double_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_COMPLEX_FLOAT, complex_float_type_node)
|
||||
@ -74,58 +84,96 @@ DEF_PRIMITIVE_TYPE (BT_COMPLEX_DOUBLE, complex_double_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_COMPLEX_LONGDOUBLE, complex_long_double_type_node)
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_PTR, ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_FILEPTR, fileptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_CONST_PTR, const_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_VOLATILE_PTR,
|
||||
build_pointer_type
|
||||
(build_qualified_type (void_type_node,
|
||||
TYPE_QUAL_VOLATILE)))
|
||||
DEF_PRIMITIVE_TYPE (BT_PTRMODE, (*lang_hooks.types.type_for_mode)(ptr_mode, 0))
|
||||
DEF_PRIMITIVE_TYPE (BT_INT_PTR, integer_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_FLOAT_PTR, float_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DOUBLE_PTR, double_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_LONGDOUBLE_PTR, long_double_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_PID, pid_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_SIZE, size_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_SSIZE, signed_size_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT32, dfloat32_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT64, dfloat64_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT128, dfloat128_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT32_PTR, dfloat32_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT64_PTR, dfloat64_ptr_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_DFLOAT128_PTR, dfloat128_ptr_type_node)
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
|
||||
DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
|
||||
|
||||
DEF_PRIMITIVE_TYPE (BT_I1, builtin_type_for_size (BITS_PER_UNIT*1, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_I2, builtin_type_for_size (BITS_PER_UNIT*2, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_I4, builtin_type_for_size (BITS_PER_UNIT*4, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_I8, builtin_type_for_size (BITS_PER_UNIT*8, 1))
|
||||
DEF_PRIMITIVE_TYPE (BT_I16, builtin_type_for_size (BITS_PER_UNIT*16, 1))
|
||||
|
||||
DEF_POINTER_TYPE (BT_PTR_CONST_STRING, BT_CONST_STRING)
|
||||
DEF_POINTER_TYPE (BT_PTR_LONG, BT_LONG)
|
||||
DEF_POINTER_TYPE (BT_PTR_PTR, BT_PTR)
|
||||
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_VOID, BT_VOID)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_BOOL, BT_BOOL)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_PTR, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_UNSIGNED, BT_UNSIGNED)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_PID, BT_PID)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_INT, BT_INT)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_UINT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_FLOAT, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_DOUBLE, BT_DOUBLE)
|
||||
/* For "long double" we use LONGDOUBLE (not LONG_DOUBLE) to
|
||||
distinguish it from two types in sequence, "long" followed by
|
||||
"double". */
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_LONGDOUBLE, BT_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT32, BT_DFLOAT32)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT64, BT_DFLOAT64)
|
||||
DEF_FUNCTION_TYPE_0 (BT_FN_DFLOAT128, BT_DFLOAT128)
|
||||
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONG, BT_LONG, BT_LONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONGLONG_LONGLONG, BT_LONGLONG, BT_LONGLONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INTMAX_INTMAX, BT_INTMAX, BT_INTMAX)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_FLOAT, BT_FLOAT, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_DOUBLE, BT_DOUBLE, BT_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_LONGDOUBLE,
|
||||
BT_LONGDOUBLE, BT_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT,
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_LONGDOUBLE,
|
||||
BT_LONGDOUBLE, BT_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT,
|
||||
BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
|
||||
BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
|
||||
BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_COMPLEX_FLOAT,
|
||||
BT_FLOAT, BT_COMPLEX_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
|
||||
BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_COMPLEX_FLOAT,
|
||||
BT_FLOAT, BT_COMPLEX_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_COMPLEX_DOUBLE,
|
||||
BT_DOUBLE, BT_COMPLEX_DOUBLE)
|
||||
BT_DOUBLE, BT_COMPLEX_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE,
|
||||
BT_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_UNSIGNED, BT_PTR, BT_UNSIGNED)
|
||||
BT_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_UINT, BT_PTR, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_PTR_SIZE, BT_PTR, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_UINT, BT_INT, BT_UINT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONG, BT_INT, BT_LONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_ULONG, BT_INT, BT_ULONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGLONG, BT_INT, BT_LONGLONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_ULONGLONG, BT_INT, BT_ULONGLONG)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_INTMAX, BT_INT, BT_INTMAX)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_UINTMAX, BT_INT, BT_UINTMAX)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_PTR, BT_INT, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_FLOAT, BT_INT, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_DOUBLE, BT_INT, BT_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_LONGDOUBLE, BT_INT, BT_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT32, BT_INT, BT_DFLOAT32)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT64, BT_INT, BT_DFLOAT64)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_DFLOAT128, BT_INT, BT_DFLOAT128)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONG_FLOAT, BT_LONG, BT_FLOAT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONG_DOUBLE, BT_LONG, BT_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONG_LONGDOUBLE, BT_LONG, BT_LONGDOUBLE)
|
||||
@ -142,27 +190,43 @@ DEF_FUNCTION_TYPE_1 (BT_FN_FLOAT_CONST_STRING, BT_FLOAT, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DOUBLE_CONST_STRING, BT_DOUBLE, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_LONGDOUBLE_CONST_STRING,
|
||||
BT_LONGDOUBLE, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_CONST_STRING, BT_DFLOAT32, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_CONST_STRING, BT_DFLOAT64, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_CONST_STRING,
|
||||
BT_DFLOAT128, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_STRING_CONST_STRING, BT_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_WORD_PTR, BT_WORD, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_INT_WINT, BT_INT, BT_WINT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_WINT_WINT, BT_WINT, BT_WINT)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT32_DFLOAT32, BT_DFLOAT32, BT_DFLOAT32)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR)
|
||||
DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT)
|
||||
|
||||
DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR)
|
||||
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_INT, BT_VOID, BT_PTR, BT_INT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_STRING_CONST_STRING,
|
||||
BT_STRING, BT_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_STRING_CONST_STRING,
|
||||
BT_STRING, BT_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_CONST_STRING,
|
||||
BT_INT, BT_CONST_STRING, BT_CONST_STRING)
|
||||
BT_INT, BT_CONST_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_CONST_STRING,
|
||||
BT_STRING, BT_CONST_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_SIZE_CONST_STRING_CONST_STRING,
|
||||
BT_SIZE, BT_CONST_STRING, BT_CONST_STRING)
|
||||
BT_SIZE, BT_CONST_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_INT,
|
||||
BT_STRING, BT_CONST_STRING, BT_INT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_PTR,
|
||||
BT_INT, BT_CONST_STRING, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_PTR,
|
||||
BT_INT, BT_INT, BT_PTR)
|
||||
BT_STRING, BT_CONST_STRING, BT_INT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_STRING_CONST_STRING_SIZE,
|
||||
BT_STRING, BT_CONST_STRING, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_FILEPTR,
|
||||
BT_INT, BT_CONST_STRING, BT_FILEPTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_INT_FILEPTR,
|
||||
BT_INT, BT_INT, BT_FILEPTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRMODE_PTR,
|
||||
BT_VOID, BT_PTRMODE, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG,
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_VALIST_REF_VALIST_ARG,
|
||||
BT_VOID, BT_VALIST_REF, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_LONG_LONG_LONG,
|
||||
BT_LONG, BT_LONG, BT_LONG)
|
||||
@ -214,12 +278,23 @@ DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_PTR_SIZE_SIZE,
|
||||
BT_PTR, BT_SIZE, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT,
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT_COMPLEX_FLOAT,
|
||||
BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT, BT_COMPLEX_FLOAT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE_COMPLEX_DOUBLE,
|
||||
BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE, BT_COMPLEX_DOUBLE)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
|
||||
BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE,
|
||||
BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE, BT_COMPLEX_LONGDOUBLE)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTR_PTR, BT_VOID, BT_PTR, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING,
|
||||
BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_SIZE_CONST_PTR_INT, BT_SIZE, BT_CONST_PTR, BT_INT)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_I1_VPTR_I1, BT_I1, BT_VOLATILE_PTR, BT_I1)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_I2_VPTR_I2, BT_I2, BT_VOLATILE_PTR, BT_I2)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_I4_VPTR_I4, BT_I4, BT_VOLATILE_PTR, BT_I4)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_I8_VPTR_I8, BT_I8, BT_VOLATILE_PTR, BT_I8)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_I16_VPTR_I16, BT_I16, BT_VOLATILE_PTR, BT_I16)
|
||||
DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_LONGPTR_LONGPTR,
|
||||
BT_BOOL, BT_PTR_LONG, BT_PTR_LONG)
|
||||
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_STRING_CONST_STRING_SIZE,
|
||||
BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE)
|
||||
@ -228,9 +303,9 @@ DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_SIZE,
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_CONST_PTR_SIZE,
|
||||
BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_PTR_CONST_PTR_SIZE,
|
||||
BT_INT, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
|
||||
BT_INT, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_INT_SIZE,
|
||||
BT_PTR, BT_PTR, BT_INT, BT_SIZE)
|
||||
BT_PTR, BT_PTR, BT_INT, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_INT_INT,
|
||||
BT_VOID, BT_PTR, BT_INT, BT_INT)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_CONST_PTR_PTR_SIZE,
|
||||
@ -239,8 +314,8 @@ DEF_FUNCTION_TYPE_3 (BT_FN_INT_STRING_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_CONST_STRING, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_PTR_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_PTR, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_FILEPTR, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_STRING_CONST_STRING_CONST_STRING_INT,
|
||||
BT_STRING, BT_CONST_STRING, BT_CONST_STRING, BT_INT)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_FLOAT_FLOAT_FLOAT_FLOAT,
|
||||
@ -261,37 +336,103 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_DOUBLE_DOUBLEPTR_DOUBLEPTR,
|
||||
BT_VOID, BT_DOUBLE, BT_DOUBLE_PTR, BT_DOUBLE_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_LONGDOUBLE_LONGDOUBLEPTR_LONGDOUBLEPTR,
|
||||
BT_VOID, BT_LONGDOUBLE, BT_LONGDOUBLE_PTR, BT_LONGDOUBLE_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_PTR_PTR_PTR, BT_VOID, BT_PTR, BT_PTR, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING,
|
||||
BT_INT, BT_CONST_STRING, BT_PTR_CONST_STRING, BT_PTR_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_INT_INT_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I1_I1, BT_BOOL, BT_VOLATILE_PTR,
|
||||
BT_I1, BT_I1)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I2_I2, BT_BOOL, BT_VOLATILE_PTR,
|
||||
BT_I2, BT_I2)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I4_I4, BT_BOOL, BT_VOLATILE_PTR,
|
||||
BT_I4, BT_I4)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I8_I8, BT_BOOL, BT_VOLATILE_PTR,
|
||||
BT_I8, BT_I8)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_BOOL_VPTR_I16_I16, BT_BOOL, BT_VOLATILE_PTR,
|
||||
BT_I16, BT_I16)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_I1_VPTR_I1_I1, BT_I1, BT_VOLATILE_PTR, BT_I1, BT_I1)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_I2_VPTR_I2_I2, BT_I2, BT_VOLATILE_PTR, BT_I2, BT_I2)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_I4_VPTR_I4_I4, BT_I4, BT_VOLATILE_PTR, BT_I4, BT_I4)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_I8_VPTR_I8_I8, BT_I8, BT_VOLATILE_PTR, BT_I8, BT_I8)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_I16_VPTR_I16_I16, BT_I16, BT_VOLATILE_PTR,
|
||||
BT_I16, BT_I16)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_VOID_OMPFN_PTR_UINT, BT_VOID, BT_PTR_FN_VOID_PTR,
|
||||
BT_PTR, BT_UINT)
|
||||
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR,
|
||||
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_PTR)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR,
|
||||
BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR,
|
||||
BT_SIZE, BT_STRING, BT_SIZE, BT_CONST_STRING, BT_CONST_PTR)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE,
|
||||
BT_PTR, BT_PTR, BT_CONST_PTR, BT_SIZE, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_PTR_PTR_INT_SIZE_SIZE,
|
||||
BT_PTR, BT_PTR, BT_INT, BT_SIZE, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE,
|
||||
BT_STRING, BT_STRING, BT_CONST_STRING, BT_SIZE, BT_SIZE)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_FILEPTR, BT_INT, BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_4 (BT_FN_VOID_OMPFN_PTR_UINT_UINT,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT, BT_UINT)
|
||||
|
||||
DEF_FUNCTION_TYPE_5 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING,
|
||||
BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_5 (BT_FN_BOOL_LONG_LONG_LONG_LONGPTR_LONGPTR,
|
||||
BT_BOOL, BT_LONG, BT_LONG, BT_LONG,
|
||||
BT_PTR_LONG, BT_PTR_LONG)
|
||||
|
||||
DEF_FUNCTION_TYPE_6 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG,
|
||||
BT_INT, BT_STRING, BT_SIZE, BT_INT, BT_SIZE,
|
||||
BT_CONST_STRING, BT_VALIST_ARG)
|
||||
DEF_FUNCTION_TYPE_6 (BT_FN_BOOL_LONG_LONG_LONG_LONG_LONGPTR_LONGPTR,
|
||||
BT_BOOL, BT_LONG, BT_LONG, BT_LONG, BT_LONG,
|
||||
BT_PTR_LONG, BT_PTR_LONG)
|
||||
DEF_FUNCTION_TYPE_6 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
|
||||
BT_LONG, BT_LONG, BT_LONG)
|
||||
|
||||
DEF_FUNCTION_TYPE_7 (BT_FN_VOID_OMPFN_PTR_UINT_LONG_LONG_LONG_LONG,
|
||||
BT_VOID, BT_PTR_FN_VOID_PTR, BT_PTR, BT_UINT,
|
||||
BT_LONG, BT_LONG, BT_LONG, BT_LONG)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_VOID_VAR, BT_VOID)
|
||||
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_INT_VAR, BT_INT)
|
||||
DEF_FUNCTION_TYPE_VAR_0 (BT_FN_PTR_VAR, BT_PTR)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_VALIST_REF_VAR,
|
||||
DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_VALIST_REF_VAR,
|
||||
BT_VOID, BT_VALIST_REF)
|
||||
DEF_FUNCTION_TYPE_VAR_1 (BT_FN_VOID_CONST_PTR_VAR,
|
||||
BT_VOID, BT_CONST_PTR)
|
||||
DEF_FUNCTION_TYPE_VAR_1 (BT_FN_INT_CONST_STRING_VAR,
|
||||
BT_INT, BT_CONST_STRING)
|
||||
BT_INT, BT_CONST_STRING)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_PTR_CONST_STRING_VAR,
|
||||
BT_INT, BT_PTR, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR,
|
||||
BT_INT, BT_FILEPTR, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_STRING_CONST_STRING_VAR,
|
||||
BT_INT, BT_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_CONST_STRING_CONST_STRING_VAR,
|
||||
BT_INT, BT_CONST_STRING, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_INT_CONST_STRING_VAR,
|
||||
BT_INT, BT_INT, BT_CONST_STRING)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_STRING_SIZE_CONST_STRING_VAR,
|
||||
BT_INT, BT_STRING, BT_SIZE, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_3 (BT_FN_SSIZE_STRING_SIZE_CONST_STRING_VAR,
|
||||
BT_SSIZE, BT_STRING, BT_SIZE, BT_CONST_STRING)
|
||||
DEF_FUNCTION_TYPE_VAR_3 (BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR,
|
||||
BT_INT, BT_FILEPTR, BT_INT, BT_CONST_STRING)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_4 (BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR,
|
||||
BT_INT, BT_STRING, BT_INT, BT_SIZE, BT_CONST_STRING)
|
||||
|
||||
DEF_FUNCTION_TYPE_VAR_5 (BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR,
|
||||
BT_INT, BT_STRING, BT_SIZE, BT_INT, BT_SIZE,
|
||||
BT_CONST_STRING)
|
||||
|
||||
DEF_POINTER_TYPE (BT_PTR_FN_VOID_VAR, BT_FN_VOID_VAR)
|
||||
DEF_FUNCTION_TYPE_3 (BT_FN_PTR_PTR_FN_VOID_VAR_PTR_SIZE,
|
||||
BT_PTR, BT_PTR_FN_VOID_VAR, BT_PTR, BT_SIZE)
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* This file contains the definitions and documentation for the
|
||||
builtins used in the GNU compiler.
|
||||
Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,13 +17,13 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Before including this file, you should define a macro:
|
||||
|
||||
DEF_BUILTIN (ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P,
|
||||
FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT)
|
||||
FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT, COND)
|
||||
|
||||
This macro will be called once for each builtin function. The
|
||||
ENUM will be of type `enum built_in_function', and will indicate
|
||||
@ -53,22 +54,30 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
exist when compiling in ANSI conformant mode.
|
||||
|
||||
ATTRs is an attribute list as defined in builtin-attrs.def that
|
||||
describes the attributes of this builtin function.
|
||||
describes the attributes of this builtin function.
|
||||
|
||||
IMPLICIT specifies condition when the builtin can be produced by
|
||||
compiler. For instance C90 reserves floorf function, but does not
|
||||
define it's meaning. When user uses floorf we may assume that the
|
||||
floorf has the meaning we expect, but we can't produce floorf by
|
||||
simplifying floor((double)float) since the runtime need not implement
|
||||
it. */
|
||||
|
||||
it.
|
||||
|
||||
The builtins is registered only if COND is true. */
|
||||
|
||||
/* A GCC builtin (like __builtin_saveregs) is provided by the
|
||||
compiler, but does not correspond to a function in the standard
|
||||
library. */
|
||||
#undef DEF_GCC_BUILTIN
|
||||
#define DEF_GCC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
|
||||
false, false, false, ATTRS, true)
|
||||
false, false, false, ATTRS, true, true)
|
||||
|
||||
/* Like DEF_GCC_BUILTIN, except we don't prepend "__builtin_". */
|
||||
#undef DEF_SYNC_BUILTIN
|
||||
#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, TYPE, BT_LAST, \
|
||||
false, false, false, ATTRS, true, true)
|
||||
|
||||
/* A library builtin (like __builtin_strchr) is a builtin equivalent
|
||||
of an ANSI/ISO standard library function. In addition to the
|
||||
@ -76,34 +85,62 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
`strchr') as well. If we cannot compute the answer using the
|
||||
builtin function, we will fall back to the standard library
|
||||
version. */
|
||||
#undef DEF_LIB_BUILTIN
|
||||
#undef DEF_LIB_BUILTIN
|
||||
#define DEF_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, false, ATTRS, true)
|
||||
true, true, false, ATTRS, true, true)
|
||||
|
||||
/* Like DEF_LIB_BUILTIN, except that the function is not one that is
|
||||
specified by ANSI/ISO C. So, when we're being fully conformant we
|
||||
ignore the version of these builtins that does not begin with
|
||||
__builtin. */
|
||||
#undef DEF_EXT_LIB_BUILTIN
|
||||
#undef DEF_EXT_LIB_BUILTIN
|
||||
#define DEF_EXT_LIB_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, true, ATTRS, false)
|
||||
true, true, true, ATTRS, false, true)
|
||||
|
||||
/* Like DEF_LIB_BUILTIN, except that the function is only a part of
|
||||
the standard in C94 or above. */
|
||||
#undef DEF_C94_BUILTIN
|
||||
#define DEF_C94_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, !flag_isoc94, ATTRS, TARGET_C99_FUNCTIONS, true)
|
||||
|
||||
/* Like DEF_LIB_BUILTIN, except that the function is only a part of
|
||||
the standard in C99 or above. */
|
||||
#undef DEF_C99_BUILTIN
|
||||
#undef DEF_C99_BUILTIN
|
||||
#define DEF_C99_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, !flag_isoc99, ATTRS, TARGET_C99_FUNCTIONS)
|
||||
true, true, !flag_isoc99, ATTRS, TARGET_C99_FUNCTIONS, true)
|
||||
|
||||
/* Builtin that is specified by C99 and C90 reserve the name for future use.
|
||||
We can still recognize the builtin in C90 mode but we can't produce it
|
||||
implicitly. */
|
||||
#undef DEF_C99_C90RES_BUILTIN
|
||||
#undef DEF_C99_C90RES_BUILTIN
|
||||
#define DEF_C99_C90RES_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, !flag_isoc99, ATTRS, TARGET_C99_FUNCTIONS)
|
||||
true, true, !flag_isoc99, ATTRS, TARGET_C99_FUNCTIONS, true)
|
||||
|
||||
/* Builtin that C99 reserve the name for future use. We can still recognize
|
||||
the builtin in C99 mode but we can't produce it implicitly. */
|
||||
#undef DEF_EXT_C99RES_BUILTIN
|
||||
#define DEF_EXT_C99RES_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
true, true, true, ATTRS, false, true)
|
||||
|
||||
/* Allocate the enum and the name for a builtin, but do not actually
|
||||
define it here at all. */
|
||||
#undef DEF_BUILTIN_STUB
|
||||
#define DEF_BUILTIN_STUB(ENUM, NAME) \
|
||||
DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, 0, 0, false, false, \
|
||||
false, 0, false, false)
|
||||
|
||||
/* Builtin used by the implementation of GNU OpenMP. None of these are
|
||||
actually implemented in the compiler; they're all in libgomp. */
|
||||
#undef DEF_GOMP_BUILTIN
|
||||
#define DEF_GOMP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
|
||||
DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
|
||||
false, true, true, ATTRS, false, flag_openmp)
|
||||
|
||||
/* Define an attribute list for math functions that are normally
|
||||
"impure" because some of them may write into global memory for
|
||||
@ -115,11 +152,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
/* Define an attribute list for math functions that are normally
|
||||
"pure" but if flag_unsafe_math_optimizations is set they are
|
||||
instead "const". This distinction accounts for the fact that some
|
||||
math functions check the rounding mode which is akin to examing
|
||||
math functions check the rounding mode which is akin to examining
|
||||
global memory. In "unsafe" mode we can be less careful. */
|
||||
#undef ATTR_MATHFN_FPROUNDING
|
||||
#define ATTR_MATHFN_FPROUNDING (flag_unsafe_math_optimizations ? \
|
||||
ATTR_CONST_NOTHROW_LIST : ATTR_PURE_NOTHROW_LIST)
|
||||
ATTR_CONST_NOTHROW_LIST : ATTR_PURE_NOTHROW_NOVOPS_LIST)
|
||||
|
||||
/* Define an attribute list for math functions that are normally
|
||||
"impure" because some of them may write into global memory for
|
||||
@ -218,9 +255,9 @@ DEF_C99_C90RES_BUILTIN (BUILT_IN_FMODL, "fmodl", BT_FN_LONGDOUBLE_LONGDOUBLE_LON
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FREXP, "frexp", BT_FN_DOUBLE_DOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPF, "frexpf", BT_FN_FLOAT_FLOAT_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_FREXPL, "frexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INTPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMA, "gamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAF, "gammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL, "gammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMA, "gamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAF, "gammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GAMMAL, "gammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_HUGE_VAL, "huge_val", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALF, "huge_valf", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_HUGE_VALL, "huge_vall", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
@ -233,6 +270,9 @@ DEF_C99_BUILTIN (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, ATTR_MA
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INF, "inf", BT_FN_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INFF, "inff", BT_FN_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INFL, "infl", BT_FN_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_J0, "j0", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_J0F, "j0f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_J0L, "j0l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
@ -242,12 +282,24 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_J1L, "j1l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_M
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_JN, "jn", BT_FN_DOUBLE_INT_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_JNF, "jnf", BT_FN_FLOAT_INT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_JNL, "jnl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LCEIL, "lceil", BT_FN_LONG_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LCEILF, "lceilf", BT_FN_LONG_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LCEILL, "lceill", BT_FN_LONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_LDEXP, "ldexp", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPF, "ldexpf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_LDEXPL, "ldexpl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LFLOOR, "lfloor", BT_FN_LONG_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LFLOORF, "lfloorf", BT_FN_LONG_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LFLOORL, "lfloorl", BT_FN_LONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMA, "lgamma", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMAF, "lgammaf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LGAMMAL, "lgammal", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLCEIL, "llceil", BT_FN_LONGLONG_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLCEILF, "llceilf", BT_FN_LONGLONG_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLCEILL, "llceill", BT_FN_LONGLONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLFLOOR, "llfloor", BT_FN_LONGLONG_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLFLOORF, "llfloorf", BT_FN_LONGLONG_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LLFLOORL, "llfloorl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LLRINT, "llrint", BT_FN_LONGLONG_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LLRINTF, "llrintf", BT_FN_LONGLONG_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_LLRINTL, "llrintl", BT_FN_LONGLONG_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
@ -278,12 +330,15 @@ DEF_C99_BUILTIN (BUILT_IN_LROUNDL, "lroundl", BT_FN_LONG_LONGDOUBLE, ATTR
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MODF, "modf", BT_FN_DOUBLE_DOUBLE_DOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFF, "modff", BT_FN_FLOAT_FLOAT_FLOATPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_MODFL, "modfl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLEPTR, ATTR_MATHFN_FPROUNDING_STORE)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL_1)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NAN, "nan", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANF, "nanf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANL, "nanl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NAND32, "nand32", BT_FN_DFLOAT32_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NAND64, "nand64", BT_FN_DFLOAT64_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NAND128, "nand128", BT_FN_DFLOAT128_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANS, "nans", BT_FN_DOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANSF, "nansf", BT_FN_FLOAT_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NANSL, "nansl", BT_FN_LONGDOUBLE_CONST_STRING, ATTR_CONST_NOTHROW_NONNULL)
|
||||
DEF_C99_BUILTIN (BUILT_IN_NEARBYINT, "nearbyint", BT_FN_DOUBLE_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_NEARBYINTF, "nearbyintf", BT_FN_FLOAT_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_NEARBYINTL, "nearbyintl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
@ -298,6 +353,9 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10, "pow10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHF
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10F, "pow10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10L, "pow10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_POWF, "powf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POWI, "powi", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POWIF, "powif", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POWIL, "powil", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_POWL, "powl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_REMAINDER, "remainder", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_REMAINDERF, "remainderf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
@ -320,6 +378,9 @@ DEF_C99_BUILTIN (BUILT_IN_SCALBLNL, "scalblnl", BT_FN_LONGDOUBLE_LONGDOUB
|
||||
DEF_C99_BUILTIN (BUILT_IN_SCALBN, "scalbn", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_SCALBNF, "scalbnf", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_C99_BUILTIN (BUILT_IN_SCALBNL, "scalbnl", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBIT, "signbit", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITF, "signbitf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNBITL, "signbitl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICAND, "significand", BT_FN_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDF, "significandf", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SIGNIFICANDL, "significandl", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
@ -358,8 +419,6 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_YNF, "ynf", BT_FN_FLOAT_INT_FLOAT, ATTR_MATHFN_
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_YNL, "ynl", BT_FN_LONGDOUBLE_INT_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
|
||||
|
||||
/* Category: _Complex math builtins. */
|
||||
/* The C99 clog function conflicts with C++ iostreams clog, see
|
||||
http://gcc.gnu.org/ml/gcc-patches/2003-09/msg00510.html */
|
||||
DEF_C99_BUILTIN (BUILT_IN_CABS, "cabs", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CABSF, "cabsf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CABSL, "cabsl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
@ -396,9 +455,12 @@ DEF_C99_BUILTIN (BUILT_IN_CEXPL, "cexpl", BT_FN_COMPLEX_LONGDOUBLE_COMPLE
|
||||
DEF_C99_BUILTIN (BUILT_IN_CIMAG, "cimag", BT_FN_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CIMAGF, "cimagf", BT_FN_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CIMAGL, "cimagl", BT_FN_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
/*DEF_C99_BUILTIN (BUILT_IN_CLOG, "clog", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)*/
|
||||
/*DEF_C99_BUILTIN (BUILT_IN_CLOGF, "clogf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)*/
|
||||
/*DEF_C99_BUILTIN (BUILT_IN_CLOGL, "clogl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)*/
|
||||
DEF_C99_BUILTIN (BUILT_IN_CLOG, "clog", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CLOGF, "clogf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CLOGL, "clogl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10, "clog10", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10F, "clog10f", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_EXT_C99RES_BUILTIN (BUILT_IN_CLOG10L, "clog10l", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_MATHFN_FPROUNDING)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CONJ, "conj", BT_FN_COMPLEX_DOUBLE_COMPLEX_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CONJF, "conjf", BT_FN_COMPLEX_FLOAT_COMPLEX_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_CONJL, "conjl", BT_FN_COMPLEX_LONGDOUBLE_COMPLEX_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
@ -433,60 +495,97 @@ DEF_C99_BUILTIN (BUILT_IN_CTANL, "ctanl", BT_FN_COMPLEX_LONGDOUBLE_COMPLE
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_BCMP, "bcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_BCOPY, "bcopy", BT_FN_VOID_CONST_PTR_PTR_SIZE, ATTR_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_BZERO, "bzero", BT_FN_VOID_PTR_SIZE, ATTR_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL_1)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_RINDEX, "rindex", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_1)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY, "stpcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRPBRK, "strpbrk", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRRCHR, "strrchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRSPN, "strspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRSTR, "strstr", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL_1_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_INDEX, "index", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMCMP, "memcmp", BT_FN_INT_CONST_PTR_CONST_PTR_SIZE, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMCPY, "memcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMMOVE, "memmove", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY, "mempcpy", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MEMSET, "memset", BT_FN_PTR_PTR_INT_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_RINDEX, "rindex", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY, "stpcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPNCPY, "stpncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCASECMP, "strcasecmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCAT, "strcat", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCHR, "strchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCMP, "strcmp", BT_FN_INT_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCPY, "strcpy", BT_FN_STRING_STRING_CONST_STRING, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRCSPN, "strcspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRDUP, "strdup", BT_FN_STRING_CONST_STRING, ATTR_MALLOC_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNDUP, "strndup", BT_FN_STRING_CONST_STRING_SIZE, ATTR_MALLOC_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRLEN, "strlen", BT_FN_SIZE_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCASECMP, "strncasecmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCAT, "strncat", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCMP, "strncmp", BT_FN_INT_CONST_STRING_CONST_STRING_SIZE, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRNCPY, "strncpy", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRPBRK, "strpbrk", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRRCHR, "strrchr", BT_FN_STRING_CONST_STRING_INT, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRSPN, "strspn", BT_FN_SIZE_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRSTR, "strstr", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_PURE_NOTHROW_NONNULL)
|
||||
|
||||
/* Category: stdio builtins. */
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPRINTF, "fprintf", BT_FN_INT_PTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_UNLOCKED, "fprintf_unlocked", BT_FN_INT_PTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPUTC, "fputc", BT_FN_INT_INT_PTR, ATTR_NOTHROW_NONNULL_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTC_UNLOCKED, "fputc_unlocked", BT_FN_INT_INT_PTR, ATTR_NOTHROW_NONNULL_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPUTS, "fputs", BT_FN_INT_CONST_STRING_PTR, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTS_UNLOCKED, "fputs_unlocked", BT_FN_INT_CONST_STRING_PTR, ATTR_NOTHROW_NONNULL_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FSCANF, "fscanf", BT_FN_INT_PTR_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FWRITE, "fwrite", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR, ATTR_NOTHROW_NONNULL_1_4)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FWRITE_UNLOCKED, "fwrite_unlocked", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_PTR, ATTR_NOTHROW_NONNULL_1_4)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPRINTF, "fprintf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_UNLOCKED, "fprintf_unlocked", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTC, "putc", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTC_UNLOCKED, "putc_unlocked", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPUTC, "fputc", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTC_UNLOCKED, "fputc_unlocked", BT_FN_INT_INT_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FPUTS, "fputs", BT_FN_INT_CONST_STRING_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPUTS_UNLOCKED, "fputs_unlocked", BT_FN_INT_CONST_STRING_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FSCANF, "fscanf", BT_FN_INT_FILEPTR_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_FWRITE, "fwrite", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FWRITE_UNLOCKED, "fwrite_unlocked", BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PRINTF, "printf", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_1_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PRINTF_UNLOCKED, "printf_unlocked", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_1_2)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTCHAR, "putchar", BT_FN_INT_INT, ATTR_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTCHAR_UNLOCKED, "putchar_unlocked", BT_FN_INT_INT, ATTR_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTS, "puts", BT_FN_INT_CONST_STRING, ATTR_NOTHROW_NONNULL_1)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTS_UNLOCKED, "puts_unlocked", BT_FN_INT_CONST_STRING, ATTR_NOTHROW_NONNULL_1)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTCHAR, "putchar", BT_FN_INT_INT, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTCHAR_UNLOCKED, "putchar_unlocked", BT_FN_INT_INT, ATTR_NULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_PUTS, "puts", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PUTS_UNLOCKED, "puts_unlocked", BT_FN_INT_CONST_STRING, ATTR_NONNULL_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_SCANF, "scanf", BT_FN_INT_CONST_STRING_VAR, ATTR_FORMAT_SCANF_1_2)
|
||||
DEF_C99_BUILTIN (BUILT_IN_SNPRINTF, "snprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_3_4)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_SPRINTF, "sprintf", BT_FN_INT_STRING_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_SSCANF, "sscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_FORMAT_SCANF_2_3)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VFPRINTF, "vfprintf", BT_FN_INT_PTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VFSCANF, "vfscanf", BT_FN_INT_PTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VFPRINTF, "vfprintf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VFSCANF, "vfscanf", BT_FN_INT_FILEPTR_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VPRINTF, "vprintf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_1_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VSCANF, "vscanf", BT_FN_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_1_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VSNPRINTF, "vsnprintf", BT_FN_INT_STRING_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_3_0)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_VSPRINTF, "vsprintf", BT_FN_INT_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
DEF_C99_BUILTIN (BUILT_IN_VSSCANF, "vsscanf", BT_FN_INT_CONST_STRING_CONST_STRING_VALIST_ARG, ATTR_FORMAT_SCANF_2_0)
|
||||
|
||||
/* Category: ctype builtins. */
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISALNUM, "isalnum", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISALPHA, "isalpha", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISASCII, "isascii", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_ISBLANK, "isblank", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISCNTRL, "iscntrl", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISDIGIT, "isdigit", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISGRAPH, "isgraph", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISLOWER, "islower", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISPRINT, "isprint", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISPUNCT, "ispunct", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISSPACE, "isspace", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISUPPER, "isupper", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ISXDIGIT, "isxdigit", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_TOASCII, "toascii", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_TOLOWER, "tolower", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_TOUPPER, "toupper", BT_FN_INT_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
|
||||
/* Category: wctype builtins. */
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWALNUM, "iswalnum", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWALPHA, "iswalpha", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN_ISWBLANK, "iswblank", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWCNTRL, "iswcntrl", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWDIGIT, "iswdigit", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWGRAPH, "iswgraph", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWLOWER, "iswlower", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWPRINT, "iswprint", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWPUNCT, "iswpunct", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWSPACE, "iswspace", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWUPPER, "iswupper", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_ISWXDIGIT, "iswxdigit", BT_FN_INT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_TOWLOWER, "towlower", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_C94_BUILTIN (BUILT_IN_TOWUPPER, "towupper", BT_FN_WINT_WINT, ATTR_PURE_NOTHROW_LIST)
|
||||
|
||||
/* Category: miscellaneous builtins. */
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ABORT, "abort", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_ABS, "abs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
@ -497,28 +596,59 @@ DEF_GCC_BUILTIN (BUILT_IN_APPLY_ARGS, "apply_args", BT_FN_PTR_VAR, ATTR_N
|
||||
DEF_GCC_BUILTIN (BUILT_IN_ARGS_INFO, "args_info", BT_FN_INT_INT, ATTR_NULL)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_CALLOC, "calloc", BT_FN_PTR_SIZE_SIZE, ATTR_MALLOC_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLASSIFY_TYPE, "classify_type", BT_FN_INT_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZL, "clzl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZLL, "clzll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZL, "clzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZLL, "clzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CONSTANT_P, "constant_p", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZ, "ctz", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZL, "ctzl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZLL, "ctzll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZ, "ctz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZIMAX, "ctzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZL, "ctzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZLL, "ctzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_DCGETTEXT, "dcgettext", BT_FN_STRING_CONST_STRING_CONST_STRING_INT, ATTR_FORMAT_ARG_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_DGETTEXT, "dgettext", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_DWARF_SP_COLUMN, "dwarf_sp_column", BT_FN_UNSIGNED, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_DWARF_SP_COLUMN, "dwarf_sp_column", BT_FN_UINT, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EH_RETURN, "eh_return", BT_FN_VOID_PTRMODE_PTR, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EH_RETURN_DATA_REGNO, "eh_return_data_regno", BT_FN_INT_INT, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECL, "execl", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECLP, "execlp", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_SENTINEL_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECLE, "execle", BT_FN_INT_CONST_STRING_CONST_STRING_VAR, ATTR_NOTHROW_SENTINEL_1)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECV, "execv", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVP, "execvp", BT_FN_INT_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_EXECVE, "execve", BT_FN_INT_CONST_STRING_PTR_CONST_STRING_PTR_CONST_STRING, ATTR_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_EXIT, "exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EXPECT, "expect", BT_FN_LONG_LONG_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EXTEND_POINTER, "extend_pointer", BT_FN_WORD_PTR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_EXTRACT_RETURN_ADDR, "extract_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UNSIGNED, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSIMAX, "ffsimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_FROB_RETURN_ADDR, "frob_return_addr", BT_FN_PTR_PTR, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_GETTEXT, "gettext", BT_FN_STRING_CONST_STRING, ATTR_FORMAT_ARG_1)
|
||||
DEF_C99_BUILTIN (BUILT_IN_IMAXABS, "imaxabs", BT_FN_INTMAX_INTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_INIT_DWARF_REG_SIZES, "init_dwarf_reg_size_table", BT_FN_VOID_PTR, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITE, "finite", BT_FN_INT_DOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEF, "finitef", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITEL, "finitel", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED32, "finited32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED64, "finited64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FINITED128, "finited128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_ISINF, "isinf", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFF, "isinff", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFL, "isinfl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD32, "isinfd32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD64, "isinfd64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISINFD128, "isinfd128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_C99_C90RES_BUILTIN (BUILT_IN_ISNAN, "isnan", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANF, "isnanf", BT_FN_INT_FLOAT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNANL, "isnanl", BT_FN_INT_LONGDOUBLE, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND32, "isnand32", BT_FN_INT_DFLOAT32, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND64, "isnand64", BT_FN_INT_DFLOAT64, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_ISNAND128, "isnand128", BT_FN_INT_DFLOAT128, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_ISGREATER, "isgreater", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_ISGREATEREQUAL, "isgreaterequal", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_ISLESS, "isless", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LIST)
|
||||
@ -530,15 +660,17 @@ DEF_C99_BUILTIN (BUILT_IN_LLABS, "llabs", BT_FN_LONGLONG_LONGLONG, ATTR_C
|
||||
DEF_GCC_BUILTIN (BUILT_IN_LONGJMP, "longjmp", BT_FN_VOID_PTR_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_MALLOC, "malloc", BT_FN_PTR_SIZE, ATTR_MALLOC_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_NEXT_ARG, "next_arg", BT_FN_PTR_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYL, "parityl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYLL, "parityll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNT, "popcount", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYIMAX, "parityimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYL, "parityl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYLL, "parityll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNT, "popcount", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTIMAX, "popcountimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_RETURN, "return", BT_FN_VOID_PTR, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UNSIGNED, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_RETURN_ADDRESS, "return_address", BT_FN_PTR_UINT, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_SAVEREGS, "saveregs", BT_FN_PTR_VAR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_SETJMP, "setjmp", BT_FN_INT_PTR, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_STDARG_START, "stdarg_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
|
||||
@ -546,8 +678,53 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_STRFMON, "strfmon", BT_FN_SSIZE_STRING_SIZE_CON
|
||||
DEF_LIB_BUILTIN (BUILT_IN_STRFTIME, "strftime", BT_FN_SIZE_STRING_SIZE_CONST_STRING_CONST_PTR, ATTR_FORMAT_STRFTIME_3_0)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_TRAP, "trap", BT_FN_VOID, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_UNWIND_INIT, "unwind_init", BT_FN_VOID, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_UPDATE_SETJMP_BUF, "update_setjmp_buf", BT_FN_VOID_PTR_INT, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_COPY, "va_copy", BT_FN_VOID_VALIST_REF_VALIST_ARG, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_END, "va_end", BT_FN_VOID_VALIST_REF, ATTR_NULL)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_VA_START, "va_start", BT_FN_VOID_VALIST_REF_VAR, ATTR_NULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN__EXIT, "_exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
DEF_C99_BUILTIN (BUILT_IN__EXIT2, "_Exit", BT_FN_VOID_INT, ATTR_NORETURN_NOTHROW_LIST)
|
||||
|
||||
/* Implementing nested functions. */
|
||||
DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto")
|
||||
|
||||
/* Implementing __builtin_setjmp. */
|
||||
DEF_BUILTIN_STUB (BUILT_IN_SETJMP_SETUP, "__builtin_setjmp_setup")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_SETJMP_DISPATCHER, "__builtin_setjmp_dispatcher")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_SETJMP_RECEIVER, "__builtin_setjmp_receiver")
|
||||
|
||||
/* Implementing variable sized local variables. */
|
||||
DEF_BUILTIN_STUB (BUILT_IN_STACK_SAVE, "__builtin_stack_save")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_STACK_RESTORE, "__builtin_stack_restore")
|
||||
|
||||
/* Object size checking builtins. */
|
||||
DEF_GCC_BUILTIN (BUILT_IN_OBJECT_SIZE, "object_size", BT_FN_SIZE_CONST_PTR_INT, ATTR_PURE_NOTHROW_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMCPY_CHK, "__memcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMMOVE_CHK, "__memmove_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMPCPY_CHK, "__mempcpy_chk", BT_FN_PTR_PTR_CONST_PTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_MEMSET_CHK, "__memset_chk", BT_FN_PTR_PTR_INT_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STPCPY_CHK, "__stpcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCAT_CHK, "__strcat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRCPY_CHK, "__strcpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCAT_CHK, "__strncat_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_STRNCPY_CHK, "__strncpy_chk", BT_FN_STRING_STRING_CONST_STRING_SIZE_SIZE, ATTR_NOTHROW_NONNULL)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SNPRINTF_CHK, "__snprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_5_6)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_SPRINTF_CHK, "__sprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_4_5)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_VSNPRINTF_CHK, "__vsnprintf_chk", BT_FN_INT_STRING_SIZE_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_5_0)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_VSPRINTF_CHK, "__vsprintf_chk", BT_FN_INT_STRING_INT_SIZE_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_4_0)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FPRINTF_CHK, "__fprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_3_4)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_PRINTF_CHK, "__printf_chk", BT_FN_INT_INT_CONST_STRING_VAR, ATTR_FORMAT_PRINTF_2_3)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_VFPRINTF_CHK, "__vfprintf_chk", BT_FN_INT_FILEPTR_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_3_0)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_VPRINTF_CHK, "__vprintf_chk", BT_FN_INT_INT_CONST_STRING_VALIST_ARG, ATTR_FORMAT_PRINTF_2_0)
|
||||
|
||||
/* Profiling hooks. */
|
||||
DEF_BUILTIN_STUB (BUILT_IN_PROFILE_FUNC_ENTER, "profile_func_enter")
|
||||
DEF_BUILTIN_STUB (BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit")
|
||||
|
||||
/* Synchronization Primitives. */
|
||||
#include "sync-builtins.def"
|
||||
|
||||
/* OpenMP builtins. */
|
||||
#include "omp-builtins.def"
|
||||
|
@ -2,7 +2,7 @@
|
||||
on information stored in GCC's tree structure. This code implements the
|
||||
-aux-info option.
|
||||
Copyright (C) 1989, 1991, 1994, 1995, 1997, 1998,
|
||||
1999, 2000, 2003 Free Software Foundation, Inc.
|
||||
1999, 2000, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Ron Guilmette (rfg@segfault.us.com).
|
||||
|
||||
This file is part of GCC.
|
||||
@ -19,8 +19,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -75,15 +75,15 @@ affix_data_type (const char *param)
|
||||
for (;;)
|
||||
{
|
||||
if (!strncmp (p, "volatile ", 9))
|
||||
{
|
||||
p += 9;
|
||||
continue;
|
||||
}
|
||||
{
|
||||
p += 9;
|
||||
continue;
|
||||
}
|
||||
if (!strncmp (p, "const ", 6))
|
||||
{
|
||||
p += 6;
|
||||
continue;
|
||||
}
|
||||
{
|
||||
p += 6;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ gen_formal_list_for_type (tree fntype, formals_style style)
|
||||
const char *this_type;
|
||||
|
||||
if (*formal_list)
|
||||
formal_list = concat (formal_list, ", ", NULL);
|
||||
formal_list = concat (formal_list, ", ", NULL);
|
||||
|
||||
this_type = gen_type ("", TREE_VALUE (formal_type), ansi);
|
||||
formal_list
|
||||
@ -167,18 +167,18 @@ gen_formal_list_for_type (tree fntype, formals_style style)
|
||||
if (!*formal_list)
|
||||
{
|
||||
if (TYPE_ARG_TYPES (fntype))
|
||||
/* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */
|
||||
formal_list = "void";
|
||||
/* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */
|
||||
formal_list = "void";
|
||||
else
|
||||
formal_list = "/* ??? */";
|
||||
formal_list = "/* ??? */";
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If there were at least some parameters, and if the formals-types-list
|
||||
petered out to a NULL (i.e. without being terminated by a
|
||||
void_type_node) then we need to tack on an ellipsis. */
|
||||
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, ", ...", NULL);
|
||||
formal_list = concat (formal_list, ", ...", NULL);
|
||||
}
|
||||
|
||||
return concat (" (", formal_list, ")", NULL);
|
||||
@ -237,20 +237,20 @@ gen_formal_list_for_func_def (tree fndecl, formals_style style)
|
||||
const char *this_formal;
|
||||
|
||||
if (*formal_list && ((style == ansi) || (style == k_and_r_names)))
|
||||
formal_list = concat (formal_list, ", ", NULL);
|
||||
formal_list = concat (formal_list, ", ", NULL);
|
||||
this_formal = gen_decl (formal_decl, 0, style);
|
||||
if (style == k_and_r_decls)
|
||||
formal_list = concat (formal_list, this_formal, "; ", NULL);
|
||||
formal_list = concat (formal_list, this_formal, "; ", NULL);
|
||||
else
|
||||
formal_list = concat (formal_list, this_formal, NULL);
|
||||
formal_list = concat (formal_list, this_formal, NULL);
|
||||
formal_decl = TREE_CHAIN (formal_decl);
|
||||
}
|
||||
if (style == ansi)
|
||||
{
|
||||
if (!DECL_ARGUMENTS (fndecl))
|
||||
formal_list = concat (formal_list, "void", NULL);
|
||||
formal_list = concat (formal_list, "void", NULL);
|
||||
if (deserves_ellipsis (TREE_TYPE (fndecl)))
|
||||
formal_list = concat (formal_list, ", ...", NULL);
|
||||
formal_list = concat (formal_list, ", ...", NULL);
|
||||
}
|
||||
if ((style == ansi) || (style == k_and_r_names))
|
||||
formal_list = concat (" (", formal_list, ")", NULL);
|
||||
@ -309,23 +309,23 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
else
|
||||
{
|
||||
switch (TREE_CODE (t))
|
||||
{
|
||||
case POINTER_TYPE:
|
||||
if (TYPE_READONLY (t))
|
||||
ret_val = concat ("const ", ret_val, NULL);
|
||||
if (TYPE_VOLATILE (t))
|
||||
ret_val = concat ("volatile ", ret_val, NULL);
|
||||
{
|
||||
case POINTER_TYPE:
|
||||
if (TYPE_READONLY (t))
|
||||
ret_val = concat ("const ", ret_val, NULL);
|
||||
if (TYPE_VOLATILE (t))
|
||||
ret_val = concat ("volatile ", ret_val, NULL);
|
||||
|
||||
ret_val = concat ("*", ret_val, NULL);
|
||||
ret_val = concat ("*", ret_val, NULL);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
|
||||
ret_val = concat ("(", ret_val, ")", NULL);
|
||||
|
||||
ret_val = gen_type (ret_val, TREE_TYPE (t), style);
|
||||
ret_val = gen_type (ret_val, TREE_TYPE (t), style);
|
||||
|
||||
return ret_val;
|
||||
return ret_val;
|
||||
|
||||
case ARRAY_TYPE:
|
||||
case ARRAY_TYPE:
|
||||
if (!COMPLETE_TYPE_P (t) || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
|
||||
ret_val = gen_type (concat (ret_val, "[]", NULL),
|
||||
TREE_TYPE (t), style);
|
||||
@ -340,23 +340,23 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
ret_val = gen_type (concat (ret_val, buff, NULL),
|
||||
TREE_TYPE (t), style);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case FUNCTION_TYPE:
|
||||
ret_val = gen_type (concat (ret_val,
|
||||
case FUNCTION_TYPE:
|
||||
ret_val = gen_type (concat (ret_val,
|
||||
gen_formal_list_for_type (t, style),
|
||||
NULL),
|
||||
TREE_TYPE (t), style);
|
||||
break;
|
||||
break;
|
||||
|
||||
case IDENTIFIER_NODE:
|
||||
data_type = IDENTIFIER_POINTER (t);
|
||||
break;
|
||||
case IDENTIFIER_NODE:
|
||||
data_type = IDENTIFIER_POINTER (t);
|
||||
break;
|
||||
|
||||
/* The following three cases are complicated by the fact that a
|
||||
user may do something really stupid, like creating a brand new
|
||||
"anonymous" type specification in a formal argument list (or as
|
||||
part of a function return type specification). For example:
|
||||
user may do something really stupid, like creating a brand new
|
||||
"anonymous" type specification in a formal argument list (or as
|
||||
part of a function return type specification). For example:
|
||||
|
||||
int f (enum { red, green, blue } color);
|
||||
|
||||
@ -364,7 +364,7 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
to represent the (anonymous) type. Thus, we have to generate the
|
||||
whole darn type specification. Yuck! */
|
||||
|
||||
case RECORD_TYPE:
|
||||
case RECORD_TYPE:
|
||||
if (TYPE_NAME (t))
|
||||
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
|
||||
else
|
||||
@ -383,7 +383,7 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
data_type = concat ("struct ", data_type, NULL);
|
||||
break;
|
||||
|
||||
case UNION_TYPE:
|
||||
case UNION_TYPE:
|
||||
if (TYPE_NAME (t))
|
||||
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
|
||||
else
|
||||
@ -402,7 +402,7 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
data_type = concat ("union ", data_type, NULL);
|
||||
break;
|
||||
|
||||
case ENUMERAL_TYPE:
|
||||
case ENUMERAL_TYPE:
|
||||
if (TYPE_NAME (t))
|
||||
data_type = IDENTIFIER_POINTER (TYPE_NAME (t));
|
||||
else
|
||||
@ -422,33 +422,33 @@ gen_type (const char *ret_val, tree t, formals_style style)
|
||||
data_type = concat ("enum ", data_type, NULL);
|
||||
break;
|
||||
|
||||
case TYPE_DECL:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (t));
|
||||
break;
|
||||
case TYPE_DECL:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (t));
|
||||
break;
|
||||
|
||||
case INTEGER_TYPE:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
|
||||
/* Normally, `unsigned' is part of the deal. Not so if it comes
|
||||
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 a type qualifier. */
|
||||
if (TREE_UNSIGNED (t) && TYPE_QUALS (t))
|
||||
if (TYPE_UNSIGNED (t) && TYPE_QUALS (t))
|
||||
data_type = concat ("unsigned ", data_type, NULL);
|
||||
break;
|
||||
|
||||
case REAL_TYPE:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
|
||||
break;
|
||||
case REAL_TYPE:
|
||||
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
|
||||
break;
|
||||
|
||||
case VOID_TYPE:
|
||||
data_type = "void";
|
||||
break;
|
||||
case VOID_TYPE:
|
||||
data_type = "void";
|
||||
break;
|
||||
|
||||
case ERROR_MARK:
|
||||
data_type = "[ERROR]";
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
if (TYPE_READONLY (t))
|
||||
ret_val = concat ("const ", ret_val, NULL);
|
||||
@ -518,11 +518,11 @@ gen_decl (tree decl, int is_func_definition, formals_style style)
|
||||
NULL);
|
||||
|
||||
/* 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
|
||||
would include its parameter-list info), rather, we only add in
|
||||
the "type" of the "type" of the function, which is really just
|
||||
the return-type of the function (and does not include the parameter
|
||||
list info). */
|
||||
add the whole "type" of the function we are considering (which
|
||||
would include its parameter-list info), rather, we only add in
|
||||
the "type" of the "type" of the function, which is really just
|
||||
the return-type of the function (and does not include the parameter
|
||||
list info). */
|
||||
|
||||
ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style);
|
||||
}
|
||||
@ -531,7 +531,7 @@ gen_decl (tree decl, int is_func_definition, formals_style style)
|
||||
|
||||
ret_val = affix_data_type (ret_val);
|
||||
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL && C_DECL_REGISTER (decl))
|
||||
ret_val = concat ("register ", ret_val, NULL);
|
||||
if (TREE_PUBLIC (decl))
|
||||
ret_val = concat ("extern ", ret_val, NULL);
|
||||
@ -554,11 +554,12 @@ gen_aux_info_record (tree fndecl, int is_definition, int is_implicit,
|
||||
if (flag_gen_aux_info)
|
||||
{
|
||||
static int compiled_from_record = 0;
|
||||
expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (fndecl));
|
||||
|
||||
/* Each output .X file must have a header line. Write one now if we
|
||||
have not yet done so. */
|
||||
|
||||
if (! compiled_from_record++)
|
||||
if (!compiled_from_record++)
|
||||
{
|
||||
/* The first line tells which directory file names are relative to.
|
||||
Currently, -aux-info works only for files in the working
|
||||
@ -569,8 +570,7 @@ gen_aux_info_record (tree fndecl, int is_definition, int is_implicit,
|
||||
/* Write the actual line of auxiliary info. */
|
||||
|
||||
fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;",
|
||||
DECL_SOURCE_FILE (fndecl),
|
||||
DECL_SOURCE_LINE (fndecl),
|
||||
xloc.file, xloc.line,
|
||||
(is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O',
|
||||
(is_definition) ? 'F' : 'C',
|
||||
gen_decl (fndecl, is_definition, ansi));
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* This file contains the definitions and documentation for the
|
||||
additional tree codes used in the GNU C++ compiler (see tree.def
|
||||
additional tree codes used in the GNU C compiler (see tree.def
|
||||
for the standard codes).
|
||||
Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998,
|
||||
1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2004, 2005 Free Software Foundation, Inc.
|
||||
Written by Benjamin Chelf <chelf@codesourcery.com>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -19,101 +19,18 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Tree nodes relevant to both C and C++. These were originally in
|
||||
cp-tree.def in the cp subdir. */
|
||||
|
||||
DEFTREECODE (SIZEOF_EXPR, "sizeof_expr", '1', 1)
|
||||
DEFTREECODE (ARROW_EXPR, "arrow_expr", 'e', 1)
|
||||
DEFTREECODE (ALIGNOF_EXPR, "alignof_expr", '1', 1)
|
||||
|
||||
/* Used to represent an expression statement. Use `EXPR_STMT_EXPR' to
|
||||
obtain the expression. */
|
||||
DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent a brace-enclosed block. The operand is
|
||||
COMPOUND_BODY. */
|
||||
DEFTREECODE (COMPOUND_STMT, "compound_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent a local declaration. The operand is
|
||||
DECL_STMT_DECL. */
|
||||
DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1)
|
||||
|
||||
/* Represents an 'if' statement. The operands are IF_COND,
|
||||
THEN_CLAUSE, and ELSE_CLAUSE, respectively. */
|
||||
DEFTREECODE (IF_STMT, "if_stmt", 'e', 3)
|
||||
|
||||
/* Used to represent a `for' statement. The operands are
|
||||
FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */
|
||||
DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4)
|
||||
|
||||
/* Used to represent a 'while' statement. The operands are WHILE_COND
|
||||
and WHILE_BODY, respectively. */
|
||||
DEFTREECODE (WHILE_STMT, "while_stmt", 'e', 2)
|
||||
|
||||
/* Used to represent a 'do' statement. The operands are DO_BODY and
|
||||
DO_COND, respectively. */
|
||||
DEFTREECODE (DO_STMT, "do_stmt", 'e', 2)
|
||||
|
||||
/* Used to represent a 'return' statement. The operand is
|
||||
RETURN_STMT_EXPR. */
|
||||
DEFTREECODE (RETURN_STMT, "return_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent a 'break' statement. */
|
||||
DEFTREECODE (BREAK_STMT, "break_stmt", 'e', 0)
|
||||
|
||||
/* Used to represent a 'continue' statement. */
|
||||
DEFTREECODE (CONTINUE_STMT, "continue_stmt", 'e', 0)
|
||||
|
||||
/* Used to represent a 'switch' statement. The operands are
|
||||
SWITCH_COND, SWITCH_BODY and SWITCH_TYPE, respectively. */
|
||||
DEFTREECODE (SWITCH_STMT, "switch_stmt", 'e', 3)
|
||||
|
||||
/* Used to represent a 'goto' statement. The operand is GOTO_DESTINATION. */
|
||||
DEFTREECODE (GOTO_STMT, "goto_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent a 'label' statement. The operand is a LABEL_DECL
|
||||
and can be obtained through the macro LABEL_STMT_LABEL. */
|
||||
DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent an inline assembly statement. */
|
||||
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
|
||||
|
||||
/* A SCOPE_STMT marks the beginning or end of a scope. If
|
||||
SCOPE_BEGIN_P holds, then this is the start of a scope. If
|
||||
SCOPE_END_P holds, then this is the end of a scope. If
|
||||
SCOPE_NULLIFIED_P holds then there turned out to be no variables in
|
||||
this scope. The SCOPE_STMT_BLOCK is the BLOCK containing the
|
||||
variables declared in this scope. */
|
||||
DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 1)
|
||||
|
||||
/* A FILE_STMT marks the spot where a function changes files. It has no
|
||||
other semantics. FILE_STMT_FILENAME gives the name. */
|
||||
DEFTREECODE (FILE_STMT, "file_stmt", 'e', 1)
|
||||
|
||||
/* Used to represent a CASE_LABEL. The operands are CASE_LOW and
|
||||
CASE_HIGH, respectively. If CASE_LOW is NULL_TREE, the label is a
|
||||
'default' label. If CASE_HIGH is NULL_TREE, the label is a normal case
|
||||
label. The CASE_LABEL_DECL is a LABEL_DECL for this node. */
|
||||
DEFTREECODE (CASE_LABEL, "case_label", 'e', 3)
|
||||
|
||||
/* A STMT_EXPR represents a statement-expression. The
|
||||
STMT_EXPR_STMT is the statement given by the expression. */
|
||||
DEFTREECODE (STMT_EXPR, "stmt_expr", 'e', 1)
|
||||
/* Tree nodes used in the C frontend. These are also shared with the
|
||||
C++ and Objective C frontends. */
|
||||
|
||||
/* A COMPOUND_LITERAL_EXPR represents a C99 compound literal. The
|
||||
COMPOUND_LITERAL_EXPR_DECL_STMT is the a DECL_STMT containing the decl
|
||||
for the anonymous object represented by the COMPOUND_LITERAL;
|
||||
the DECL_INITIAL of that decl is the CONSTRUCTOR that initializes
|
||||
the compound literal. */
|
||||
DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", 'e', 1)
|
||||
|
||||
/* A CLEANUP_STMT marks the point at which a declaration is fully
|
||||
constructed. If, after this point, the CLEANUP_DECL goes out of
|
||||
scope, the CLEANUP_EXPR must be run. */
|
||||
DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 2)
|
||||
DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", tcc_expression, 1)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Top level configure fragment for GNU C - C language.
|
||||
# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005 Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GCC.
|
||||
|
||||
@ -15,12 +15,12 @@
|
||||
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with GCC; see the file COPYING. If not, write to
|
||||
#the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
#Boston, MA 02111-1307, USA.
|
||||
#the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
#Boston, MA 02110-1301, USA.
|
||||
|
||||
# This file c-config-lang.c is a special pseudo config-lang.in file
|
||||
# for the language C. It has limited use, specifically to record the
|
||||
# files used by C that have garbage collection GTY macros in them
|
||||
# which therefore need to be scanned by gengtype.c.
|
||||
|
||||
gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-parse.in \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c"
|
||||
gtfiles="\$(srcdir)/c-lang.c \$(srcdir)/c-tree.h \$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-pragma.c \$(srcdir)/c-objc-common.c \$(srcdir)/c-parser.c"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Language-level data type conversion for GNU C.
|
||||
Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003
|
||||
Copyright (C) 1987, 1988, 1991, 1998, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
|
||||
/* This file contains the functions for converting C expressions
|
||||
@ -33,7 +33,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "flags.h"
|
||||
#include "convert.h"
|
||||
#include "c-common.h"
|
||||
#include "c-tree.h"
|
||||
#include "langhooks.h"
|
||||
#include "toplev.h"
|
||||
#include "target.h"
|
||||
|
||||
/* Change of width--truncation and extension of integers or reals--
|
||||
is represented with NOP_EXPR. Proper functioning of many things
|
||||
@ -67,14 +70,25 @@ convert (tree type, tree expr)
|
||||
{
|
||||
tree e = expr;
|
||||
enum tree_code code = TREE_CODE (type);
|
||||
const char *invalid_conv_diag;
|
||||
|
||||
if (type == TREE_TYPE (expr)
|
||||
|| TREE_CODE (expr) == ERROR_MARK
|
||||
|| code == ERROR_MARK || TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
||||
if (type == error_mark_node
|
||||
|| expr == error_mark_node
|
||||
|| TREE_TYPE (expr) == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if ((invalid_conv_diag
|
||||
= targetm.invalid_conversion (TREE_TYPE (expr), type)))
|
||||
{
|
||||
error (invalid_conv_diag);
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
if (type == TREE_TYPE (expr))
|
||||
return expr;
|
||||
|
||||
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))
|
||||
return fold (build1 (NOP_EXPR, type, expr));
|
||||
return fold_convert (type, expr);
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
|
||||
return error_mark_node;
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)
|
||||
@ -83,25 +97,11 @@ convert (tree type, tree expr)
|
||||
return error_mark_node;
|
||||
}
|
||||
if (code == VOID_TYPE)
|
||||
return build1 (CONVERT_EXPR, type, e);
|
||||
#if 0
|
||||
/* This is incorrect. A truncation can't be stripped this way.
|
||||
Extensions will be stripped by the use of get_unwidened. */
|
||||
if (TREE_CODE (expr) == NOP_EXPR)
|
||||
return convert (type, TREE_OPERAND (expr, 0));
|
||||
#endif
|
||||
return fold_convert (type, e);
|
||||
if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)
|
||||
return fold (convert_to_integer (type, e));
|
||||
if (code == BOOLEAN_TYPE)
|
||||
{
|
||||
tree t = c_common_truthvalue_conversion (expr);
|
||||
/* If it returns a NOP_EXPR, we must fold it here to avoid
|
||||
infinite recursion between fold () and convert (). */
|
||||
if (TREE_CODE (t) == NOP_EXPR)
|
||||
return fold (build1 (NOP_EXPR, type, TREE_OPERAND (t, 0)));
|
||||
else
|
||||
return fold (build1 (NOP_EXPR, type, t));
|
||||
}
|
||||
return fold_convert (type, c_objc_common_truthvalue_conversion (expr));
|
||||
if (code == POINTER_TYPE || code == REFERENCE_TYPE)
|
||||
return fold (convert_to_pointer (type, e));
|
||||
if (code == REAL_TYPE)
|
||||
@ -110,6 +110,9 @@ convert (tree type, tree expr)
|
||||
return fold (convert_to_complex (type, e));
|
||||
if (code == VECTOR_TYPE)
|
||||
return fold (convert_to_vector (type, e));
|
||||
if ((code == RECORD_TYPE || code == UNION_TYPE)
|
||||
&& lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
|
||||
return e;
|
||||
|
||||
error ("conversion to non-scalar type requested");
|
||||
return error_mark_node;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Define builtin-in macros for the C family front ends.
|
||||
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,14 +15,15 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "version.h"
|
||||
#include "flags.h"
|
||||
#include "real.h"
|
||||
#include "c-common.h"
|
||||
@ -31,6 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "except.h" /* For USING_SJLJ_EXCEPTIONS. */
|
||||
#include "toplev.h"
|
||||
#include "tm_p.h" /* Target prototypes. */
|
||||
#include "target.h"
|
||||
|
||||
#ifndef TARGET_OS_CPP_BUILTINS
|
||||
# define TARGET_OS_CPP_BUILTINS()
|
||||
@ -51,10 +53,14 @@ static void builtin_define_with_value_n (const char *, const char *,
|
||||
static void builtin_define_with_int_value (const char *, HOST_WIDE_INT);
|
||||
static void builtin_define_with_hex_fp_value (const char *, tree,
|
||||
int, const char *,
|
||||
const char *,
|
||||
const char *);
|
||||
static void builtin_define_stdint_macros (void);
|
||||
static void builtin_define_type_max (const char *, tree, int);
|
||||
static void builtin_define_type_precision (const char *, tree);
|
||||
static void builtin_define_float_constants (const char *, const char *,
|
||||
static void builtin_define_float_constants (const char *,
|
||||
const char *,
|
||||
const char *,
|
||||
tree);
|
||||
static void define__GNUC__ (void);
|
||||
|
||||
@ -65,9 +71,13 @@ builtin_define_type_precision (const char *name, tree type)
|
||||
builtin_define_with_int_value (name, TYPE_PRECISION (type));
|
||||
}
|
||||
|
||||
/* Define the float.h constants for TYPE using NAME_PREFIX and FP_SUFFIX. */
|
||||
/* Define the float.h constants for TYPE using NAME_PREFIX, FP_SUFFIX,
|
||||
and FP_CAST. */
|
||||
static void
|
||||
builtin_define_float_constants (const char *name_prefix, const char *fp_suffix, tree type)
|
||||
builtin_define_float_constants (const char *name_prefix,
|
||||
const char *fp_suffix,
|
||||
const char *fp_cast,
|
||||
tree type)
|
||||
{
|
||||
/* Used to convert radix-based values to base 10 values in several cases.
|
||||
|
||||
@ -86,6 +96,7 @@ builtin_define_float_constants (const char *name_prefix, const char *fp_suffix,
|
||||
int decimal_dig;
|
||||
|
||||
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
gcc_assert (fmt->b != 10);
|
||||
|
||||
/* The radix of the exponent representation. */
|
||||
if (type == float_type_node)
|
||||
@ -205,19 +216,24 @@ builtin_define_float_constants (const char *name_prefix, const char *fp_suffix,
|
||||
}
|
||||
}
|
||||
sprintf (name, "__%s_MAX__", name_prefix);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
|
||||
|
||||
/* The minimum normalized positive floating-point number,
|
||||
b**(emin-1). */
|
||||
sprintf (name, "__%s_MIN__", name_prefix);
|
||||
sprintf (buf, "0x1p%d", (fmt->emin - 1) * fmt->log2_b);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
|
||||
|
||||
/* The difference between 1 and the least value greater than 1 that is
|
||||
representable in the given floating point type, b**(1-p). */
|
||||
sprintf (name, "__%s_EPSILON__", name_prefix);
|
||||
sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
|
||||
if (fmt->pnan < fmt->p)
|
||||
/* This is an IBM extended double format, so 1.0 + any double is
|
||||
representable precisely. */
|
||||
sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
|
||||
else
|
||||
sprintf (buf, "0x1p%d", (1 - fmt->p) * fmt->log2_b);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix, fp_cast);
|
||||
|
||||
/* For C++ std::numeric_limits<T>::denorm_min. The minimum denormalized
|
||||
positive floating-point number, b**(emin-p). Zero for formats that
|
||||
@ -227,7 +243,7 @@ builtin_define_float_constants (const char *name_prefix, const char *fp_suffix,
|
||||
{
|
||||
sprintf (buf, "0x1p%d", (fmt->emin - fmt->p) * fmt->log2_b);
|
||||
builtin_define_with_hex_fp_value (name, type, decimal_dig,
|
||||
buf, fp_suffix);
|
||||
buf, fp_suffix, fp_cast);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -235,6 +251,9 @@ builtin_define_float_constants (const char *name_prefix, const char *fp_suffix,
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
|
||||
sprintf (name, "__%s_HAS_DENORM__", name_prefix);
|
||||
builtin_define_with_value (name, fmt->has_denorm ? "1" : "0", 0);
|
||||
|
||||
/* For C++ std::numeric_limits<T>::has_infinity. */
|
||||
sprintf (name, "__%s_HAS_INFINITY__", name_prefix);
|
||||
builtin_define_with_int_value (name,
|
||||
@ -248,6 +267,70 @@ builtin_define_float_constants (const char *name_prefix, const char *fp_suffix,
|
||||
builtin_define_with_int_value (name, MODE_HAS_NANS (TYPE_MODE (type)));
|
||||
}
|
||||
|
||||
/* Define __DECx__ constants for TYPE using NAME_PREFIX and SUFFIX. */
|
||||
static void
|
||||
builtin_define_decimal_float_constants (const char *name_prefix,
|
||||
const char *suffix,
|
||||
tree type)
|
||||
{
|
||||
const struct real_format *fmt;
|
||||
char name[64], buf[128], *p;
|
||||
int digits;
|
||||
|
||||
fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
|
||||
|
||||
/* The number of radix digits, p, in the significand. */
|
||||
sprintf (name, "__%s_MANT_DIG__", name_prefix);
|
||||
builtin_define_with_int_value (name, fmt->p);
|
||||
|
||||
/* The minimum negative int x such that b**(x-1) is a normalized float. */
|
||||
sprintf (name, "__%s_MIN_EXP__", name_prefix);
|
||||
sprintf (buf, "(%d)", fmt->emin);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
|
||||
/* The maximum int x such that b**(x-1) is a representable float. */
|
||||
sprintf (name, "__%s_MAX_EXP__", name_prefix);
|
||||
builtin_define_with_int_value (name, fmt->emax);
|
||||
|
||||
/* Compute the minimum representable value. */
|
||||
sprintf (name, "__%s_MIN__", name_prefix);
|
||||
sprintf (buf, "1E%d%s", fmt->emin, suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
|
||||
/* Compute the maximum representable value. */
|
||||
sprintf (name, "__%s_MAX__", name_prefix);
|
||||
p = buf;
|
||||
for (digits = fmt->p; digits; digits--)
|
||||
{
|
||||
*p++ = '9';
|
||||
if (digits == fmt->p)
|
||||
*p++ = '.';
|
||||
}
|
||||
*p = 0;
|
||||
/* fmt->p plus 1, to account for the decimal point. */
|
||||
sprintf (&buf[fmt->p + 1], "E%d%s", fmt->emax, suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
|
||||
/* Compute epsilon (the difference between 1 and least value greater
|
||||
than 1 representable). */
|
||||
sprintf (name, "__%s_EPSILON__", name_prefix);
|
||||
sprintf (buf, "1E-%d%s", fmt->p - 1, suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
|
||||
/* Minimum denormalized postive decimal value. */
|
||||
sprintf (name, "__%s_DEN__", name_prefix);
|
||||
p = buf;
|
||||
for (digits = fmt->p; digits > 1; digits--)
|
||||
{
|
||||
*p++ = '0';
|
||||
if (digits == fmt->p)
|
||||
*p++ = '.';
|
||||
}
|
||||
*p = 0;
|
||||
sprintf (&buf[fmt->p], "1E%d%s", fmt->emin, suffix);
|
||||
builtin_define_with_value (name, buf, 0);
|
||||
}
|
||||
|
||||
/* Define __GNUC__, __GNUC_MINOR__ and __GNUC_PATCHLEVEL__. */
|
||||
static void
|
||||
define__GNUC__ (void)
|
||||
@ -256,10 +339,9 @@ define__GNUC__ (void)
|
||||
([^0-9]*-)?[0-9]+[.][0-9]+([.][0-9]+)?([- ].*)? */
|
||||
const char *q, *v = version_string;
|
||||
|
||||
while (*v && ! ISDIGIT (*v))
|
||||
while (*v && !ISDIGIT (*v))
|
||||
v++;
|
||||
if (!*v || (v > version_string && v[-1] != '-'))
|
||||
abort ();
|
||||
gcc_assert (*v && (v <= version_string || v[-1] == '-'));
|
||||
|
||||
q = v;
|
||||
while (ISDIGIT (*v))
|
||||
@ -268,8 +350,8 @@ define__GNUC__ (void)
|
||||
if (c_dialect_cxx ())
|
||||
builtin_define_with_value_n ("__GNUG__", q, v - q);
|
||||
|
||||
if (*v != '.' || !ISDIGIT (v[1]))
|
||||
abort ();
|
||||
gcc_assert (*v == '.' && ISDIGIT (v[1]));
|
||||
|
||||
q = ++v;
|
||||
while (ISDIGIT (*v))
|
||||
v++;
|
||||
@ -277,8 +359,7 @@ define__GNUC__ (void)
|
||||
|
||||
if (*v == '.')
|
||||
{
|
||||
if (!ISDIGIT (v[1]))
|
||||
abort ();
|
||||
gcc_assert (ISDIGIT (v[1]));
|
||||
q = ++v;
|
||||
while (ISDIGIT (*v))
|
||||
v++;
|
||||
@ -287,8 +368,24 @@ define__GNUC__ (void)
|
||||
else
|
||||
builtin_define_with_value_n ("__GNUC_PATCHLEVEL__", "0", 1);
|
||||
|
||||
if (*v && *v != ' ' && *v != '-')
|
||||
abort ();
|
||||
gcc_assert (!*v || *v == ' ' || *v == '-');
|
||||
}
|
||||
|
||||
/* Define macros used by <stdint.h>. Currently only defines limits
|
||||
for intmax_t, used by the testsuite. */
|
||||
static void
|
||||
builtin_define_stdint_macros (void)
|
||||
{
|
||||
int intmax_long;
|
||||
if (intmax_type_node == long_long_integer_type_node)
|
||||
intmax_long = 2;
|
||||
else if (intmax_type_node == long_integer_type_node)
|
||||
intmax_long = 1;
|
||||
else if (intmax_type_node == integer_type_node)
|
||||
intmax_long = 0;
|
||||
else
|
||||
gcc_unreachable ();
|
||||
builtin_define_type_max ("__INTMAX_MAX__", intmax_type_node, intmax_long);
|
||||
}
|
||||
|
||||
/* Hook that registers front end and target-specific built-ins. */
|
||||
@ -306,7 +403,7 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
|
||||
if (c_dialect_cxx ())
|
||||
{
|
||||
if (SUPPORTS_ONE_ONLY)
|
||||
if (flag_weak && SUPPORTS_ONE_ONLY)
|
||||
cpp_define (pfile, "__GXX_WEAK__=1");
|
||||
else
|
||||
cpp_define (pfile, "__GXX_WEAK__=0");
|
||||
@ -323,19 +420,19 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
if (flag_abi_version == 0)
|
||||
/* Use a very large value so that:
|
||||
|
||||
#if __GXX_ABI_VERSION >= <value for version X>
|
||||
#if __GXX_ABI_VERSION >= <value for version X>
|
||||
|
||||
will work whether the user explicitly says "-fabi-version=x" or
|
||||
"-fabi-version=0". Do not use INT_MAX because that will be
|
||||
different from system to system. */
|
||||
builtin_define_with_int_value ("__GXX_ABI_VERSION", 999999);
|
||||
else if (flag_abi_version == 1)
|
||||
/* Due to an historical accident, this version had the value
|
||||
/* Due to a historical accident, this version had the value
|
||||
"102". */
|
||||
builtin_define_with_int_value ("__GXX_ABI_VERSION", 102);
|
||||
else
|
||||
/* Newer versions have values 1002, 1003, .... */
|
||||
builtin_define_with_int_value ("__GXX_ABI_VERSION",
|
||||
builtin_define_with_int_value ("__GXX_ABI_VERSION",
|
||||
1000 + flag_abi_version);
|
||||
|
||||
/* libgcc needs to know this. */
|
||||
@ -352,14 +449,33 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
|
||||
builtin_define_type_precision ("__CHAR_BIT__", char_type_node);
|
||||
|
||||
/* stdint.h (eventually) and the testsuite need to know these. */
|
||||
builtin_define_stdint_macros ();
|
||||
|
||||
/* float.h needs to know these. */
|
||||
|
||||
builtin_define_with_int_value ("__FLT_EVAL_METHOD__",
|
||||
TARGET_FLT_EVAL_METHOD);
|
||||
|
||||
builtin_define_float_constants ("FLT", "F", float_type_node);
|
||||
builtin_define_float_constants ("DBL", "", double_type_node);
|
||||
builtin_define_float_constants ("LDBL", "L", long_double_type_node);
|
||||
/* And decfloat.h needs this. */
|
||||
builtin_define_with_int_value ("__DEC_EVAL_METHOD__",
|
||||
TARGET_DEC_EVAL_METHOD);
|
||||
|
||||
builtin_define_float_constants ("FLT", "F", "%s", float_type_node);
|
||||
/* Cast the double precision constants when single precision constants are
|
||||
specified. The correct result is computed by the compiler when using
|
||||
macros that include a cast. This has the side-effect of making the value
|
||||
unusable in const expressions. */
|
||||
if (flag_single_precision_constant)
|
||||
builtin_define_float_constants ("DBL", "L", "((double)%s)", double_type_node);
|
||||
else
|
||||
builtin_define_float_constants ("DBL", "", "%s", double_type_node);
|
||||
builtin_define_float_constants ("LDBL", "L", "%s", long_double_type_node);
|
||||
|
||||
/* For decfloat.h. */
|
||||
builtin_define_decimal_float_constants ("DEC32", "DF", dfloat32_type_node);
|
||||
builtin_define_decimal_float_constants ("DEC64", "DD", dfloat64_type_node);
|
||||
builtin_define_decimal_float_constants ("DEC128", "DL", dfloat128_type_node);
|
||||
|
||||
/* For use in assembly language. */
|
||||
builtin_define_with_value ("__REGISTER_PREFIX__", REGISTER_PREFIX, 0);
|
||||
@ -368,6 +484,8 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
/* Misc. */
|
||||
builtin_define_with_value ("__VERSION__", version_string, 1);
|
||||
|
||||
cpp_define (pfile, "__GNUC_GNU_INLINE__");
|
||||
|
||||
/* Definitions for LP64 model. */
|
||||
if (TYPE_PRECISION (long_integer_type_node) == 64
|
||||
&& POINTER_SIZE == 64
|
||||
@ -394,6 +512,11 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
cpp_define (pfile, "__FINITE_MATH_ONLY__=1");
|
||||
else
|
||||
cpp_define (pfile, "__FINITE_MATH_ONLY__=0");
|
||||
if (flag_pic)
|
||||
{
|
||||
builtin_define_with_int_value ("__pic__", flag_pic);
|
||||
builtin_define_with_int_value ("__PIC__", flag_pic);
|
||||
}
|
||||
|
||||
if (flag_iso)
|
||||
cpp_define (pfile, "__STRICT_ANSI__");
|
||||
@ -401,13 +524,31 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
if (!flag_signed_char)
|
||||
cpp_define (pfile, "__CHAR_UNSIGNED__");
|
||||
|
||||
if (c_dialect_cxx () && TREE_UNSIGNED (wchar_type_node))
|
||||
if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
|
||||
cpp_define (pfile, "__WCHAR_UNSIGNED__");
|
||||
|
||||
/* Make the choice of ObjC runtime visible to source code. */
|
||||
if (c_dialect_objc () && flag_next_runtime)
|
||||
cpp_define (pfile, "__NEXT_RUNTIME__");
|
||||
|
||||
/* Show the availability of some target pragmas. */
|
||||
if (flag_mudflap || targetm.handle_pragma_redefine_extname)
|
||||
cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME");
|
||||
|
||||
if (targetm.handle_pragma_extern_prefix)
|
||||
cpp_define (pfile, "__PRAGMA_EXTERN_PREFIX");
|
||||
|
||||
/* Make the choice of the stack protector runtime visible to source code.
|
||||
The macro names and values here were chosen for compatibility with an
|
||||
earlier implementation, i.e. ProPolice. */
|
||||
if (flag_stack_protect == 2)
|
||||
cpp_define (pfile, "__SSP_ALL__=2");
|
||||
else if (flag_stack_protect == 1)
|
||||
cpp_define (pfile, "__SSP__=1");
|
||||
|
||||
if (flag_openmp)
|
||||
cpp_define (pfile, "_OPENMP=200505");
|
||||
|
||||
/* A straightforward target hook doesn't work, because of problems
|
||||
linking that hook's body when part of non-C front ends. */
|
||||
# define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
|
||||
@ -417,6 +558,15 @@ c_cpp_builtins (cpp_reader *pfile)
|
||||
TARGET_CPU_CPP_BUILTINS ();
|
||||
TARGET_OS_CPP_BUILTINS ();
|
||||
TARGET_OBJFMT_CPP_BUILTINS ();
|
||||
|
||||
/* Support the __declspec keyword by turning them into attributes.
|
||||
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. */
|
||||
if (TARGET_DECLSPEC)
|
||||
builtin_define ("__declspec(x)=__attribute__((x))");
|
||||
}
|
||||
|
||||
/* Pass an object-like macro. If it doesn't lie in the user's
|
||||
@ -432,7 +582,7 @@ void
|
||||
builtin_define_std (const char *macro)
|
||||
{
|
||||
size_t len = strlen (macro);
|
||||
char *buff = alloca (len + 5);
|
||||
char *buff = (char *) alloca (len + 5);
|
||||
char *p = buff + 2;
|
||||
char *q = p + len;
|
||||
|
||||
@ -478,7 +628,7 @@ builtin_define_with_value (const char *macro, const char *expansion, int is_str)
|
||||
if (is_str)
|
||||
extra += 2; /* space for two quote marks */
|
||||
|
||||
buf = alloca (mlen + elen + extra);
|
||||
buf = (char *) alloca (mlen + elen + extra);
|
||||
if (is_str)
|
||||
sprintf (buf, "%s=\"%s\"", macro, expansion);
|
||||
else
|
||||
@ -496,7 +646,7 @@ builtin_define_with_value_n (const char *macro, const char *expansion, size_t el
|
||||
size_t mlen = strlen (macro);
|
||||
|
||||
/* Space for an = and a NUL. */
|
||||
buf = alloca (mlen + elen + 2);
|
||||
buf = (char *) alloca (mlen + elen + 2);
|
||||
memcpy (buf, macro, mlen);
|
||||
buf[mlen] = '=';
|
||||
memcpy (buf + mlen + 1, expansion, elen);
|
||||
@ -514,7 +664,7 @@ builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
|
||||
size_t vlen = 18;
|
||||
size_t extra = 2; /* space for = and NUL. */
|
||||
|
||||
buf = alloca (mlen + vlen + extra);
|
||||
buf = (char *) alloca (mlen + vlen + extra);
|
||||
memcpy (buf, macro, mlen);
|
||||
buf[mlen] = '=';
|
||||
sprintf (buf + mlen + 1, HOST_WIDE_INT_PRINT_DEC, value);
|
||||
@ -526,10 +676,12 @@ builtin_define_with_int_value (const char *macro, HOST_WIDE_INT value)
|
||||
static void
|
||||
builtin_define_with_hex_fp_value (const char *macro,
|
||||
tree type ATTRIBUTE_UNUSED, int digits,
|
||||
const char *hex_str, const char *fp_suffix)
|
||||
const char *hex_str,
|
||||
const char *fp_suffix,
|
||||
const char *fp_cast)
|
||||
{
|
||||
REAL_VALUE_TYPE real;
|
||||
char dec_str[64], buf[256];
|
||||
char dec_str[64], buf1[256], buf2[256];
|
||||
|
||||
/* Hex values are really cool and convenient, except that they're
|
||||
not supported in strict ISO C90 mode. First, the "p-" sequence
|
||||
@ -544,8 +696,13 @@ builtin_define_with_hex_fp_value (const char *macro,
|
||||
real_from_string (&real, hex_str);
|
||||
real_to_decimal (dec_str, &real, sizeof (dec_str), digits, 0);
|
||||
|
||||
sprintf (buf, "%s=%s%s", macro, dec_str, fp_suffix);
|
||||
cpp_define (parse_in, buf);
|
||||
/* Assemble the macro in the following fashion
|
||||
macro = fp_cast [dec_str fp_suffix] */
|
||||
sprintf (buf1, "%s%s", dec_str, fp_suffix);
|
||||
sprintf (buf2, fp_cast, buf1);
|
||||
sprintf (buf1, "%s=%s", macro, buf2);
|
||||
|
||||
cpp_define (parse_in, buf1);
|
||||
}
|
||||
|
||||
/* Define MAX for TYPE based on the precision of the type. IS_LONG is
|
||||
@ -578,13 +735,14 @@ builtin_define_type_max (const char *macro, tree type, int is_long)
|
||||
case 32: idx = 4; break;
|
||||
case 64: idx = 6; break;
|
||||
case 128: idx = 8; break;
|
||||
default: abort ();
|
||||
default: gcc_unreachable ();
|
||||
}
|
||||
|
||||
value = values[idx + TREE_UNSIGNED (type)];
|
||||
suffix = suffixes[is_long * 2 + TREE_UNSIGNED (type)];
|
||||
value = values[idx + TYPE_UNSIGNED (type)];
|
||||
suffix = suffixes[is_long * 2 + TYPE_UNSIGNED (type)];
|
||||
|
||||
buf = alloca (strlen (macro) + 1 + strlen (value) + strlen (suffix) + 1);
|
||||
buf = (char *) alloca (strlen (macro) + 1 + strlen (value)
|
||||
+ strlen (suffix) + 1);
|
||||
sprintf (buf, "%s=%s%s", macro, value, suffix);
|
||||
|
||||
cpp_define (parse_in, buf);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Tree-dumping functionality for C-family languages.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
|
||||
Written by Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -32,15 +32,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
void
|
||||
dump_stmt (dump_info_p di, tree t)
|
||||
{
|
||||
dump_int (di, "line", STMT_LINENO (t));
|
||||
}
|
||||
|
||||
/* Dump the next statement after STMT. */
|
||||
|
||||
void
|
||||
dump_next_stmt (dump_info_p di, tree t)
|
||||
{
|
||||
dump_child ("next", TREE_CHAIN (t));
|
||||
if (EXPR_HAS_LOCATION (t))
|
||||
dump_int (di, "line", EXPR_LINENO (t));
|
||||
}
|
||||
|
||||
/* Dump any C-specific tree codes and attributes of common codes. */
|
||||
@ -61,129 +54,6 @@ c_dump_tree (void *dump_info, tree t)
|
||||
dump_string (di, "bitfield");
|
||||
break;
|
||||
|
||||
case ASM_STMT:
|
||||
dump_stmt (di, t);
|
||||
if (ASM_VOLATILE_P (t))
|
||||
dump_string (di, "volatile");
|
||||
dump_child ("strg", ASM_STRING (t));
|
||||
dump_child ("outs", ASM_OUTPUTS (t));
|
||||
dump_child ("ins", ASM_INPUTS (t));
|
||||
dump_child ("clbr", ASM_CLOBBERS (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case BREAK_STMT:
|
||||
case CONTINUE_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case CASE_LABEL:
|
||||
/* Note that a case label is not like other statements; there is
|
||||
no way to get the line-number of a case label. */
|
||||
dump_child ("low", CASE_LOW (t));
|
||||
dump_child ("high", CASE_HIGH (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case CLEANUP_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("decl", CLEANUP_DECL (t));
|
||||
dump_child ("expr", CLEANUP_EXPR (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case COMPOUND_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("body", COMPOUND_BODY (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case DECL_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("decl", DECL_STMT_DECL (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case DO_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("body", DO_BODY (t));
|
||||
dump_child ("cond", DO_COND (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case EXPR_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("expr", EXPR_STMT_EXPR (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case FOR_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("init", FOR_INIT_STMT (t));
|
||||
dump_child ("cond", FOR_COND (t));
|
||||
dump_child ("expr", FOR_EXPR (t));
|
||||
dump_child ("body", FOR_BODY (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case GOTO_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("dest", GOTO_DESTINATION (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case IF_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("cond", IF_COND (t));
|
||||
dump_child ("then", THEN_CLAUSE (t));
|
||||
dump_child ("else", ELSE_CLAUSE (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case LABEL_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("labl", LABEL_STMT_LABEL (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case RETURN_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("expr", RETURN_STMT_EXPR (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case SWITCH_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("cond", SWITCH_COND (t));
|
||||
dump_child ("body", SWITCH_BODY (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case WHILE_STMT:
|
||||
dump_stmt (di, t);
|
||||
dump_child ("cond", WHILE_COND (t));
|
||||
dump_child ("body", WHILE_BODY (t));
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case SCOPE_STMT:
|
||||
dump_stmt (di, t);
|
||||
if (SCOPE_BEGIN_P (t))
|
||||
dump_string (di, "begn");
|
||||
else
|
||||
dump_string (di, "end");
|
||||
if (SCOPE_NULLIFIED_P (t))
|
||||
dump_string (di, "null");
|
||||
if (!SCOPE_NO_CLEANUPS_P (t))
|
||||
dump_string (di, "clnp");
|
||||
dump_next_stmt (di, t);
|
||||
break;
|
||||
|
||||
case STMT_EXPR:
|
||||
dump_child ("stmt", STMT_EXPR_STMT (t));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -32,14 +32,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
/* Issue an ISO C99 pedantic warning MSGID. */
|
||||
|
||||
void
|
||||
pedwarn_c99 (const char *msgid, ...)
|
||||
pedwarn_c99 (const char *gmsgid, ...)
|
||||
{
|
||||
diagnostic_info diagnostic;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, msgid);
|
||||
diagnostic_set_info (&diagnostic, msgid, &ap, input_location,
|
||||
flag_isoc99 ? pedantic_error_kind () : DK_WARNING);
|
||||
|
||||
va_start (ap, gmsgid);
|
||||
diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
|
||||
flag_isoc99 ? pedantic_error_kind () : DK_WARNING);
|
||||
report_diagnostic (&diagnostic);
|
||||
va_end (ap);
|
||||
}
|
||||
@ -50,14 +50,14 @@ pedwarn_c99 (const char *msgid, ...)
|
||||
(There is no flag_c90.) */
|
||||
|
||||
void
|
||||
pedwarn_c90 (const char *msgid, ...)
|
||||
pedwarn_c90 (const char *gmsgid, ...)
|
||||
{
|
||||
diagnostic_info diagnostic;
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, msgid);
|
||||
diagnostic_set_info (&diagnostic, msgid, &ap, input_location,
|
||||
flag_isoc99 ? DK_WARNING : pedantic_error_kind ());
|
||||
va_start (ap, gmsgid);
|
||||
diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
|
||||
flag_isoc99 ? DK_WARNING : pedantic_error_kind ());
|
||||
report_diagnostic (&diagnostic);
|
||||
va_end (ap);
|
||||
}
|
||||
|
308
contrib/gcc/c-format.h
Normal file
308
contrib/gcc/c-format.h
Normal file
@ -0,0 +1,308 @@
|
||||
/* Check calls to formatted I/O functions (-Wformat).
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_C_FORMAT_H
|
||||
#define GCC_C_FORMAT_H
|
||||
|
||||
/* The meaningfully distinct length modifiers for format checking recognized
|
||||
by GCC. */
|
||||
enum format_lengths
|
||||
{
|
||||
FMT_LEN_none,
|
||||
FMT_LEN_hh,
|
||||
FMT_LEN_h,
|
||||
FMT_LEN_l,
|
||||
FMT_LEN_ll,
|
||||
FMT_LEN_L,
|
||||
FMT_LEN_z,
|
||||
FMT_LEN_t,
|
||||
FMT_LEN_j,
|
||||
FMT_LEN_H,
|
||||
FMT_LEN_D,
|
||||
FMT_LEN_DD,
|
||||
FMT_LEN_MAX
|
||||
};
|
||||
|
||||
|
||||
/* The standard versions in which various format features appeared. */
|
||||
enum format_std_version
|
||||
{
|
||||
STD_C89,
|
||||
STD_C94,
|
||||
STD_C9L, /* C99, but treat as C89 if -Wno-long-long. */
|
||||
STD_C99,
|
||||
STD_EXT
|
||||
};
|
||||
|
||||
/* Flags that may apply to a particular kind of format checked by GCC. */
|
||||
enum
|
||||
{
|
||||
/* This format converts arguments of types determined by the
|
||||
format string. */
|
||||
FMT_FLAG_ARG_CONVERT = 1,
|
||||
/* The scanf allocation 'a' kludge applies to this format kind. */
|
||||
FMT_FLAG_SCANF_A_KLUDGE = 2,
|
||||
/* A % during parsing a specifier is allowed to be a modified % rather
|
||||
that indicating the format is broken and we are out-of-sync. */
|
||||
FMT_FLAG_FANCY_PERCENT_OK = 4,
|
||||
/* With $ operand numbers, it is OK to reference the same argument more
|
||||
than once. */
|
||||
FMT_FLAG_DOLLAR_MULTIPLE = 8,
|
||||
/* This format type uses $ operand numbers (strfmon doesn't). */
|
||||
FMT_FLAG_USE_DOLLAR = 16,
|
||||
/* Zero width is bad in this type of format (scanf). */
|
||||
FMT_FLAG_ZERO_WIDTH_BAD = 32,
|
||||
/* Empty precision specification is OK in this type of format (printf). */
|
||||
FMT_FLAG_EMPTY_PREC_OK = 64,
|
||||
/* Gaps are allowed in the arguments with $ operand numbers if all
|
||||
arguments are pointers (scanf). */
|
||||
FMT_FLAG_DOLLAR_GAP_POINTER_OK = 128
|
||||
/* Not included here: details of whether width or precision may occur
|
||||
(controlled by width_char and precision_char); details of whether
|
||||
'*' can be used for these (width_type and precision_type); details
|
||||
of whether length modifiers can occur (length_char_specs). */
|
||||
};
|
||||
|
||||
|
||||
/* Structure describing a length modifier supported in format checking, and
|
||||
possibly a doubled version such as "hh". */
|
||||
typedef struct
|
||||
{
|
||||
/* Name of the single-character length modifier. */
|
||||
const char *name;
|
||||
/* Index into a format_char_info.types array. */
|
||||
enum format_lengths index;
|
||||
/* Standard version this length appears in. */
|
||||
enum format_std_version std;
|
||||
/* Same, if the modifier can be repeated, or NULL if it can't. */
|
||||
const char *double_name;
|
||||
enum format_lengths double_index;
|
||||
enum format_std_version double_std;
|
||||
} format_length_info;
|
||||
|
||||
|
||||
/* Structure describing the combination of a conversion specifier
|
||||
(or a set of specifiers which act identically) and a length modifier. */
|
||||
typedef struct
|
||||
{
|
||||
/* The standard version this combination of length and type appeared in.
|
||||
This is only relevant if greater than those for length and type
|
||||
individually; otherwise it is ignored. */
|
||||
enum format_std_version std;
|
||||
/* The name to use for the type, if different from that generated internally
|
||||
(e.g., "signed size_t"). */
|
||||
const char *name;
|
||||
/* The type itself. */
|
||||
tree *type;
|
||||
} format_type_detail;
|
||||
|
||||
|
||||
/* Macros to fill out tables of these. */
|
||||
#define NOARGUMENTS { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
|
||||
#define BADLEN { 0, NULL, NULL }
|
||||
#define NOLENGTHS { BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }
|
||||
|
||||
|
||||
/* Structure describing a format conversion specifier (or a set of specifiers
|
||||
which act identically), and the length modifiers used with it. */
|
||||
typedef struct format_char_info
|
||||
{
|
||||
const char *format_chars;
|
||||
int pointer_count;
|
||||
enum format_std_version std;
|
||||
/* Types accepted for each length modifier. */
|
||||
format_type_detail types[FMT_LEN_MAX];
|
||||
/* List of other modifier characters allowed with these specifiers.
|
||||
This lists flags, and additionally "w" for width, "p" for precision
|
||||
(right precision, for strfmon), "#" for left precision (strfmon),
|
||||
"a" for scanf "a" allocation extension (not applicable in C99 mode),
|
||||
"*" for scanf suppression, and "E" and "O" for those strftime
|
||||
modifiers. */
|
||||
const char *flag_chars;
|
||||
/* List of additional flags describing these conversion specifiers.
|
||||
"c" for generic character pointers being allowed, "2" for strftime
|
||||
two digit year formats, "3" for strftime formats giving two digit
|
||||
years in some locales, "4" for "2" which becomes "3" with an "E" modifier,
|
||||
"o" if use of strftime "O" is a GNU extension beyond C99,
|
||||
"W" if the argument is a pointer which is dereferenced and written into,
|
||||
"R" if the argument is a pointer which is dereferenced and read from,
|
||||
"i" for printf integer formats where the '0' flag is ignored with
|
||||
precision, and "[" for the starting character of a scanf scanset. */
|
||||
const char *flags2;
|
||||
/* If this format conversion character consumes more than one argument,
|
||||
CHAIN points to information about the next argument. For later
|
||||
arguments, only POINTER_COUNT, TYPES, and the "c", "R", and "W" flags
|
||||
in FLAGS2 are used. */
|
||||
const struct format_char_info *chain;
|
||||
} format_char_info;
|
||||
|
||||
|
||||
/* Structure describing a flag accepted by some kind of format. */
|
||||
typedef struct
|
||||
{
|
||||
/* The flag character in question (0 for end of array). */
|
||||
int flag_char;
|
||||
/* Zero if this entry describes the flag character in general, or a
|
||||
nonzero character that may be found in flags2 if it describes the
|
||||
flag when used with certain formats only. If the latter, only
|
||||
the first such entry found that applies to the current conversion
|
||||
specifier is used; the values of 'name' and 'long_name' it supplies
|
||||
will be used, if non-NULL and the standard version is higher than
|
||||
the unpredicated one, for any pedantic warning. For example, 'o'
|
||||
for strftime formats (meaning 'O' is an extension over C99). */
|
||||
int predicate;
|
||||
/* Nonzero if the next character after this flag in the format should
|
||||
be skipped ('=' in strfmon), zero otherwise. */
|
||||
int skip_next_char;
|
||||
/* The name to use for this flag in diagnostic messages. For example,
|
||||
N_("'0' flag"), N_("field width"). */
|
||||
const char *name;
|
||||
/* Long name for this flag in diagnostic messages; currently only used for
|
||||
"ISO C does not support ...". For example, N_("the 'I' printf flag"). */
|
||||
const char *long_name;
|
||||
/* The standard version in which it appeared. */
|
||||
enum format_std_version std;
|
||||
} format_flag_spec;
|
||||
|
||||
|
||||
/* Structure describing a combination of flags that is bad for some kind
|
||||
of format. */
|
||||
typedef struct
|
||||
{
|
||||
/* The first flag character in question (0 for end of array). */
|
||||
int flag_char1;
|
||||
/* The second flag character. */
|
||||
int flag_char2;
|
||||
/* Nonzero if the message should say that the first flag is ignored with
|
||||
the second, zero if the combination should simply be objected to. */
|
||||
int ignored;
|
||||
/* Zero if this entry applies whenever this flag combination occurs,
|
||||
a nonzero character from flags2 if it only applies in some
|
||||
circumstances (e.g. 'i' for printf formats ignoring 0 with precision). */
|
||||
int predicate;
|
||||
} format_flag_pair;
|
||||
|
||||
|
||||
/* Structure describing a particular kind of format processed by GCC. */
|
||||
typedef struct
|
||||
{
|
||||
/* The name of this kind of format, for use in diagnostics. Also
|
||||
the name of the attribute (without preceding and following __). */
|
||||
const char *name;
|
||||
/* Specifications of the length modifiers accepted; possibly NULL. */
|
||||
const format_length_info *length_char_specs;
|
||||
/* Details of the conversion specification characters accepted. */
|
||||
const format_char_info *conversion_specs;
|
||||
/* String listing the flag characters that are accepted. */
|
||||
const char *flag_chars;
|
||||
/* String listing modifier characters (strftime) accepted. May be NULL. */
|
||||
const char *modifier_chars;
|
||||
/* Details of the flag characters, including pseudo-flags. */
|
||||
const format_flag_spec *flag_specs;
|
||||
/* Details of bad combinations of flags. */
|
||||
const format_flag_pair *bad_flag_pairs;
|
||||
/* Flags applicable to this kind of format. */
|
||||
int flags;
|
||||
/* Flag character to treat a width as, or 0 if width not used. */
|
||||
int width_char;
|
||||
/* Flag character to treat a left precision (strfmon) as,
|
||||
or 0 if left precision not used. */
|
||||
int left_precision_char;
|
||||
/* Flag character to treat a precision (for strfmon, right precision) as,
|
||||
or 0 if precision not used. */
|
||||
int precision_char;
|
||||
/* If a flag character has the effect of suppressing the conversion of
|
||||
an argument ('*' in scanf), that flag character, otherwise 0. */
|
||||
int suppression_char;
|
||||
/* Flag character to treat a length modifier as (ignored if length
|
||||
modifiers not used). Need not be placed in flag_chars for conversion
|
||||
specifiers, but is used to check for bad combinations such as length
|
||||
modifier with assignment suppression in scanf. */
|
||||
int length_code_char;
|
||||
/* Pointer to type of argument expected if '*' is used for a width,
|
||||
or NULL if '*' not used for widths. */
|
||||
tree *width_type;
|
||||
/* Pointer to type of argument expected if '*' is used for a precision,
|
||||
or NULL if '*' not used for precisions. */
|
||||
tree *precision_type;
|
||||
} format_kind_info;
|
||||
|
||||
#define T_I &integer_type_node
|
||||
#define T89_I { STD_C89, NULL, T_I }
|
||||
#define T_L &long_integer_type_node
|
||||
#define T89_L { STD_C89, NULL, T_L }
|
||||
#define T_LL &long_long_integer_type_node
|
||||
#define T9L_LL { STD_C9L, NULL, T_LL }
|
||||
#define TEX_LL { STD_EXT, NULL, T_LL }
|
||||
#define T_S &short_integer_type_node
|
||||
#define T89_S { STD_C89, NULL, T_S }
|
||||
#define T_UI &unsigned_type_node
|
||||
#define T89_UI { STD_C89, NULL, T_UI }
|
||||
#define T_UL &long_unsigned_type_node
|
||||
#define T89_UL { STD_C89, NULL, T_UL }
|
||||
#define T_ULL &long_long_unsigned_type_node
|
||||
#define T9L_ULL { STD_C9L, NULL, T_ULL }
|
||||
#define TEX_ULL { STD_EXT, NULL, T_ULL }
|
||||
#define T_US &short_unsigned_type_node
|
||||
#define T89_US { STD_C89, NULL, T_US }
|
||||
#define T_F &float_type_node
|
||||
#define T89_F { STD_C89, NULL, T_F }
|
||||
#define T99_F { STD_C99, NULL, T_F }
|
||||
#define T_D &double_type_node
|
||||
#define T89_D { STD_C89, NULL, T_D }
|
||||
#define T99_D { STD_C99, NULL, T_D }
|
||||
#define T_LD &long_double_type_node
|
||||
#define T89_LD { STD_C89, NULL, T_LD }
|
||||
#define T99_LD { STD_C99, NULL, T_LD }
|
||||
#define T_C &char_type_node
|
||||
#define T89_C { STD_C89, NULL, T_C }
|
||||
#define T_SC &signed_char_type_node
|
||||
#define T99_SC { STD_C99, NULL, T_SC }
|
||||
#define T_UC &unsigned_char_type_node
|
||||
#define T99_UC { STD_C99, NULL, T_UC }
|
||||
#define T_V &void_type_node
|
||||
#define T89_V { STD_C89, NULL, T_V }
|
||||
#define T_W &wchar_type_node
|
||||
#define T94_W { STD_C94, "wchar_t", T_W }
|
||||
#define TEX_W { STD_EXT, "wchar_t", T_W }
|
||||
#define T_WI &wint_type_node
|
||||
#define T94_WI { STD_C94, "wint_t", T_WI }
|
||||
#define TEX_WI { STD_EXT, "wint_t", T_WI }
|
||||
#define T_ST &size_type_node
|
||||
#define T99_ST { STD_C99, "size_t", T_ST }
|
||||
#define T_SST &signed_size_type_node
|
||||
#define T99_SST { STD_C99, "signed size_t", T_SST }
|
||||
#define T_PD &ptrdiff_type_node
|
||||
#define T99_PD { STD_C99, "ptrdiff_t", T_PD }
|
||||
#define T_UPD &unsigned_ptrdiff_type_node
|
||||
#define T99_UPD { STD_C99, "unsigned ptrdiff_t", T_UPD }
|
||||
#define T_IM &intmax_type_node
|
||||
#define T99_IM { STD_C99, "intmax_t", T_IM }
|
||||
#define T_UIM &uintmax_type_node
|
||||
#define T99_UIM { STD_C99, "uintmax_t", T_UIM }
|
||||
#define T_D32 &dfloat32_type_node
|
||||
#define TEX_D32 { STD_EXT, "_Decimal32", T_D32 }
|
||||
#define T_D64 &dfloat64_type_node
|
||||
#define TEX_D64 { STD_EXT, "_Decimal64", T_D64 }
|
||||
#define T_D128 &dfloat128_type_node
|
||||
#define TEX_D128 { STD_EXT, "_Decimal128", T_D128 }
|
||||
|
||||
#endif /* GCC_C_FORMAT_H */
|
226
contrib/gcc/c-gimplify.c
Normal file
226
contrib/gcc/c-gimplify.c
Normal file
@ -0,0 +1,226 @@
|
||||
/* Tree lowering pass. This pass gimplifies the tree representation built
|
||||
by the C-based front ends. The structure of gimplified, or
|
||||
language-independent, trees is dictated by the grammar described in this
|
||||
file.
|
||||
Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
|
||||
Re-written to support lowering of whole function trees, documentation
|
||||
and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "varray.h"
|
||||
#include "c-tree.h"
|
||||
#include "c-common.h"
|
||||
#include "tree-gimple.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "basic-block.h"
|
||||
#include "tree-flow.h"
|
||||
#include "tree-inline.h"
|
||||
#include "diagnostic.h"
|
||||
#include "langhooks.h"
|
||||
#include "langhooks-def.h"
|
||||
#include "flags.h"
|
||||
#include "rtl.h"
|
||||
#include "toplev.h"
|
||||
#include "tree-dump.h"
|
||||
#include "c-pretty-print.h"
|
||||
#include "cgraph.h"
|
||||
|
||||
|
||||
/* The gimplification pass converts the language-dependent trees
|
||||
(ld-trees) emitted by the parser into language-independent trees
|
||||
(li-trees) that are the target of SSA analysis and transformations.
|
||||
|
||||
Language-independent trees are based on the SIMPLE intermediate
|
||||
representation used in the McCAT compiler framework:
|
||||
|
||||
"Designing the McCAT Compiler Based on a Family of Structured
|
||||
Intermediate Representations,"
|
||||
L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
|
||||
Proceedings of the 5th International Workshop on Languages and
|
||||
Compilers for Parallel Computing, no. 757 in Lecture Notes in
|
||||
Computer Science, New Haven, Connecticut, pp. 406-420,
|
||||
Springer-Verlag, August 3-5, 1992.
|
||||
|
||||
http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
|
||||
|
||||
Basically, we walk down gimplifying the nodes that we encounter. As we
|
||||
walk back up, we check that they fit our constraints, and copy them
|
||||
into temporaries if not. */
|
||||
|
||||
/* Gimplification of statement trees. */
|
||||
|
||||
/* Convert the tree representation of FNDECL from C frontend trees to
|
||||
GENERIC. */
|
||||
|
||||
void
|
||||
c_genericize (tree fndecl)
|
||||
{
|
||||
FILE *dump_orig;
|
||||
int local_dump_flags;
|
||||
struct cgraph_node *cgn;
|
||||
|
||||
/* Dump the C-specific tree IR. */
|
||||
dump_orig = dump_begin (TDI_original, &local_dump_flags);
|
||||
if (dump_orig)
|
||||
{
|
||||
fprintf (dump_orig, "\n;; Function %s",
|
||||
lang_hooks.decl_printable_name (fndecl, 2));
|
||||
fprintf (dump_orig, " (%s)\n",
|
||||
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
|
||||
fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
|
||||
fprintf (dump_orig, "\n");
|
||||
|
||||
if (local_dump_flags & TDF_RAW)
|
||||
dump_node (DECL_SAVED_TREE (fndecl),
|
||||
TDF_SLIM | local_dump_flags, dump_orig);
|
||||
else
|
||||
print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl));
|
||||
fprintf (dump_orig, "\n");
|
||||
|
||||
dump_end (TDI_original, dump_orig);
|
||||
}
|
||||
|
||||
/* Go ahead and gimplify for now. */
|
||||
gimplify_function_tree (fndecl);
|
||||
|
||||
/* Dump the genericized tree IR. */
|
||||
dump_function (TDI_generic, fndecl);
|
||||
|
||||
/* Genericize all nested functions now. We do things in this order so
|
||||
that items like VLA sizes are expanded properly in the context of
|
||||
the correct function. */
|
||||
cgn = cgraph_node (fndecl);
|
||||
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
|
||||
c_genericize (cgn->decl);
|
||||
}
|
||||
|
||||
static void
|
||||
add_block_to_enclosing (tree block)
|
||||
{
|
||||
tree enclosing;
|
||||
|
||||
for (enclosing = gimple_current_bind_expr ();
|
||||
enclosing; enclosing = TREE_CHAIN (enclosing))
|
||||
if (BIND_EXPR_BLOCK (enclosing))
|
||||
break;
|
||||
|
||||
enclosing = BIND_EXPR_BLOCK (enclosing);
|
||||
BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
|
||||
}
|
||||
|
||||
/* Genericize a scope by creating a new BIND_EXPR.
|
||||
BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
|
||||
In the latter case, we need to create a new BLOCK and add it to the
|
||||
BLOCK_SUBBLOCKS of the enclosing block.
|
||||
BODY is a chain of C _STMT nodes for the contents of the scope, to be
|
||||
genericized. */
|
||||
|
||||
tree
|
||||
c_build_bind_expr (tree block, tree body)
|
||||
{
|
||||
tree decls, bind;
|
||||
|
||||
if (block == NULL_TREE)
|
||||
decls = NULL_TREE;
|
||||
else if (TREE_CODE (block) == BLOCK)
|
||||
decls = BLOCK_VARS (block);
|
||||
else
|
||||
{
|
||||
decls = block;
|
||||
if (DECL_ARTIFICIAL (decls))
|
||||
block = NULL_TREE;
|
||||
else
|
||||
{
|
||||
block = make_node (BLOCK);
|
||||
BLOCK_VARS (block) = decls;
|
||||
add_block_to_enclosing (block);
|
||||
}
|
||||
}
|
||||
|
||||
if (!body)
|
||||
body = build_empty_stmt ();
|
||||
if (decls || block)
|
||||
{
|
||||
bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
|
||||
TREE_SIDE_EFFECTS (bind) = 1;
|
||||
}
|
||||
else
|
||||
bind = body;
|
||||
|
||||
return bind;
|
||||
}
|
||||
|
||||
/* Gimplification of expression trees. */
|
||||
|
||||
/* Gimplify a C99 compound literal expression. This just means adding
|
||||
the DECL_EXPR before the current statement and using its anonymous
|
||||
decl instead. */
|
||||
|
||||
static enum gimplify_status
|
||||
gimplify_compound_literal_expr (tree *expr_p, tree *pre_p)
|
||||
{
|
||||
tree decl_s = COMPOUND_LITERAL_EXPR_DECL_STMT (*expr_p);
|
||||
tree decl = DECL_EXPR_DECL (decl_s);
|
||||
|
||||
/* This decl isn't mentioned in the enclosing block, so add it to the
|
||||
list of temps. FIXME it seems a bit of a kludge to say that
|
||||
anonymous artificial vars aren't pushed, but everything else is. */
|
||||
if (DECL_NAME (decl) == NULL_TREE && !DECL_SEEN_IN_BIND_EXPR_P (decl))
|
||||
gimple_add_tmp_var (decl);
|
||||
|
||||
gimplify_and_add (decl_s, pre_p);
|
||||
*expr_p = decl;
|
||||
return GS_OK;
|
||||
}
|
||||
|
||||
/* Do C-specific gimplification. Args are as for gimplify_expr. */
|
||||
|
||||
int
|
||||
c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED)
|
||||
{
|
||||
enum tree_code code = TREE_CODE (*expr_p);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case DECL_EXPR:
|
||||
/* This is handled mostly by gimplify.c, but we have to deal with
|
||||
not warning about int x = x; as it is a GCC extension to turn off
|
||||
this warning but only if warn_init_self is zero. */
|
||||
if (TREE_CODE (DECL_EXPR_DECL (*expr_p)) == VAR_DECL
|
||||
&& !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
|
||||
&& !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
|
||||
&& (DECL_INITIAL (DECL_EXPR_DECL (*expr_p))
|
||||
== DECL_EXPR_DECL (*expr_p))
|
||||
&& !warn_init_self)
|
||||
TREE_NO_WARNING (DECL_EXPR_DECL (*expr_p)) = 1;
|
||||
return GS_UNHANDLED;
|
||||
|
||||
case COMPOUND_LITERAL_EXPR:
|
||||
return gimplify_compound_literal_expr (expr_p, pre_p);
|
||||
|
||||
default:
|
||||
return GS_UNHANDLED;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
/* Set up combined include path chain for the preprocessor.
|
||||
Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Broken out of cppinit.c and cppfiles.c and rewritten Mar 2003.
|
||||
|
||||
@ -16,11 +17,13 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "machmode.h"
|
||||
#include "target.h"
|
||||
#include "tm.h"
|
||||
#include "cpplib.h"
|
||||
#include "prefix.h"
|
||||
@ -35,7 +38,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
# define INO_T_EQ(A, B) (!memcmp (&(A), &(B), sizeof (A)))
|
||||
# define INO_T_COPY(DEST, SRC) memcpy(&(DEST), &(SRC), sizeof (SRC))
|
||||
#else
|
||||
# if (defined _WIN32 && ! defined (_UWIN)) || defined __MSDOS__
|
||||
# if (defined _WIN32 && !defined (_UWIN)) || defined __MSDOS__
|
||||
# define INO_T_EQ(A, B) 0
|
||||
# else
|
||||
# define INO_T_EQ(A, B) ((A) == (B))
|
||||
@ -43,8 +46,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
# define INO_T_COPY(DEST, SRC) (DEST) = (SRC)
|
||||
#endif
|
||||
|
||||
static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
|
||||
|
||||
static void add_env_var_paths (const char *, int);
|
||||
static void add_standard_paths (const char *, const char *, int);
|
||||
static void add_standard_paths (const char *, const char *, const char *, int);
|
||||
static void free_path (struct cpp_dir *, int);
|
||||
static void merge_include_chains (cpp_reader *, int);
|
||||
static struct cpp_dir *remove_duplicates (cpp_reader *, struct cpp_dir *,
|
||||
@ -107,18 +112,19 @@ add_env_var_paths (const char *env_var, int chain)
|
||||
path = xstrdup (".");
|
||||
else
|
||||
{
|
||||
path = xmalloc (q - p + 1);
|
||||
path = XNEWVEC (char, q - p + 1);
|
||||
memcpy (path, p, q - p);
|
||||
path[q - p] = '\0';
|
||||
}
|
||||
|
||||
add_path (path, chain, chain == SYSTEM);
|
||||
add_path (path, chain, chain == SYSTEM, false);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append the standard include chain defined in cppdefault.c. */
|
||||
static void
|
||||
add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
|
||||
add_standard_paths (const char *sysroot, const char *iprefix,
|
||||
const char *imultilib, int cxx_stdinc)
|
||||
{
|
||||
const struct default_include *p;
|
||||
size_t len;
|
||||
@ -126,7 +132,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
|
||||
if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0)
|
||||
{
|
||||
/* Look for directories that start with the standard prefix.
|
||||
"Translate" them, ie. replace /usr/local/lib/gcc... with
|
||||
"Translate" them, i.e. replace /usr/local/lib/gcc... with
|
||||
IPREFIX and search them first. */
|
||||
for (p = cpp_include_defaults; p->fname; p++)
|
||||
{
|
||||
@ -140,7 +146,9 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
|
||||
if (!strncmp (p->fname, cpp_GCC_INCLUDE_DIR, len))
|
||||
{
|
||||
char *str = concat (iprefix, p->fname + len, NULL);
|
||||
add_path (str, SYSTEM, p->cxx_aware);
|
||||
if (p->multilib && imultilib)
|
||||
str = concat (str, dir_separator_str, imultilib, NULL);
|
||||
add_path (str, SYSTEM, p->cxx_aware, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,7 +166,10 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
|
||||
else
|
||||
str = update_path (p->fname, p->component);
|
||||
|
||||
add_path (str, SYSTEM, p->cxx_aware);
|
||||
if (p->multilib && imultilib)
|
||||
str = concat (str, dir_separator_str, imultilib, NULL);
|
||||
|
||||
add_path (str, SYSTEM, p->cxx_aware, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -169,6 +180,7 @@ add_standard_paths (const char *sysroot, const char *iprefix, int cxx_stdinc)
|
||||
JOIN, unless it duplicates JOIN in which case the last path is
|
||||
removed. Return the head of the resulting chain. Any of HEAD,
|
||||
JOIN and SYSTEM can be NULL. */
|
||||
|
||||
static struct cpp_dir *
|
||||
remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
|
||||
struct cpp_dir *system, struct cpp_dir *join,
|
||||
@ -189,7 +201,13 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
|
||||
if (errno != ENOENT)
|
||||
cpp_errno (pfile, CPP_DL_ERROR, cur->name);
|
||||
else
|
||||
reason = REASON_NOENT;
|
||||
{
|
||||
/* If -Wmissing-include-dirs is given, warn. */
|
||||
cpp_options *opts = cpp_get_options (pfile);
|
||||
if (opts->warn_missing_include_dirs && cur->user_supplied_p)
|
||||
cpp_errno (pfile, CPP_DL_WARNING, cur->name);
|
||||
reason = REASON_NOENT;
|
||||
}
|
||||
}
|
||||
else if (!S_ISDIR (st.st_mode))
|
||||
cpp_error_with_line (pfile, CPP_DL_ERROR, 0, 0,
|
||||
@ -202,7 +220,8 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
|
||||
/* Remove this one if it is in the system chain. */
|
||||
reason = REASON_DUP_SYS;
|
||||
for (tmp = system; tmp; tmp = tmp->next)
|
||||
if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev)
|
||||
if (INO_T_EQ (tmp->ino, cur->ino) && tmp->dev == cur->dev
|
||||
&& cur->construct == tmp->construct)
|
||||
break;
|
||||
|
||||
if (!tmp)
|
||||
@ -210,14 +229,16 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
|
||||
/* Duplicate of something earlier in the same chain? */
|
||||
reason = REASON_DUP;
|
||||
for (tmp = head; tmp != cur; tmp = tmp->next)
|
||||
if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev)
|
||||
if (INO_T_EQ (cur->ino, tmp->ino) && cur->dev == tmp->dev
|
||||
&& cur->construct == tmp->construct)
|
||||
break;
|
||||
|
||||
if (tmp == cur
|
||||
/* Last in the chain and duplicate of JOIN? */
|
||||
&& !(cur->next == NULL && join
|
||||
&& INO_T_EQ (cur->ino, join->ino)
|
||||
&& cur->dev == join->dev))
|
||||
&& cur->dev == join->dev
|
||||
&& cur->construct == join->construct))
|
||||
{
|
||||
/* Unique, so keep this directory. */
|
||||
pcur = &cur->next;
|
||||
@ -241,9 +262,10 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
|
||||
|
||||
We can't just merge the lists and then uniquify them because then
|
||||
we may lose directories from the <> search path that should be
|
||||
there; consider -Ifoo -Ibar -I- -Ifoo -Iquux. It is however safe
|
||||
to treat -Ibar -Ifoo -I- -Ifoo -Iquux as if written -Ibar -I- -Ifoo
|
||||
-Iquux. */
|
||||
there; consider -iquote foo -iquote bar -Ifoo -Iquux. It is
|
||||
however safe to treat -iquote bar -iquote foo -Ifoo -Iquux as if
|
||||
written -iquote bar -Ifoo -Iquux. */
|
||||
|
||||
static void
|
||||
merge_include_chains (cpp_reader *pfile, int verbose)
|
||||
{
|
||||
@ -298,31 +320,11 @@ split_quote_chain (void)
|
||||
quote_ignores_source_dir = true;
|
||||
}
|
||||
|
||||
/* Add PATH to the include chain CHAIN. PATH must be malloc-ed and
|
||||
NUL-terminated. */
|
||||
/* Add P to the chain specified by CHAIN. */
|
||||
|
||||
void
|
||||
add_path (char *path, int chain, int cxx_aware)
|
||||
add_cpp_dir_path (cpp_dir *p, int chain)
|
||||
{
|
||||
struct cpp_dir *p;
|
||||
|
||||
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
|
||||
/* Convert all backslashes to slashes. The native CRT stat()
|
||||
function does not recognise a directory that ends in a backslash
|
||||
(unless it is a drive root dir, such "c:\"). Forward slashes,
|
||||
trailing or otherwise, cause no problems for stat(). */
|
||||
char* c;
|
||||
for (c = path; *c; c++)
|
||||
if (*c == '\\') *c = '/';
|
||||
#endif
|
||||
|
||||
p = xmalloc (sizeof (struct cpp_dir));
|
||||
p->next = NULL;
|
||||
p->name = path;
|
||||
if (chain == SYSTEM || chain == AFTER)
|
||||
p->sysp = 1 + !cxx_aware;
|
||||
else
|
||||
p->sysp = 0;
|
||||
|
||||
if (tails[chain])
|
||||
tails[chain]->next = p;
|
||||
else
|
||||
@ -330,12 +332,42 @@ add_path (char *path, int chain, int cxx_aware)
|
||||
tails[chain] = p;
|
||||
}
|
||||
|
||||
/* Add PATH to the include chain CHAIN. PATH must be malloc-ed and
|
||||
NUL-terminated. */
|
||||
void
|
||||
add_path (char *path, int chain, int cxx_aware, bool user_supplied_p)
|
||||
{
|
||||
cpp_dir *p;
|
||||
|
||||
#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
|
||||
/* Convert all backslashes to slashes. The native CRT stat()
|
||||
function does not recognize a directory that ends in a backslash
|
||||
(unless it is a drive root dir, such "c:\"). Forward slashes,
|
||||
trailing or otherwise, cause no problems for stat(). */
|
||||
char* c;
|
||||
for (c = path; *c; c++)
|
||||
if (*c == '\\') *c = '/';
|
||||
#endif
|
||||
|
||||
p = XNEW (cpp_dir);
|
||||
p->next = NULL;
|
||||
p->name = path;
|
||||
if (chain == SYSTEM || chain == AFTER)
|
||||
p->sysp = 1 + !cxx_aware;
|
||||
else
|
||||
p->sysp = 0;
|
||||
p->construct = 0;
|
||||
p->user_supplied_p = user_supplied_p;
|
||||
|
||||
add_cpp_dir_path (p, chain);
|
||||
}
|
||||
|
||||
/* Exported function to handle include chain merging, duplicate
|
||||
removal, and registration with cpplib. */
|
||||
void
|
||||
register_include_chains (cpp_reader *pfile, const char *sysroot,
|
||||
const char *iprefix, int stdinc, int cxx_stdinc,
|
||||
int verbose)
|
||||
const char *iprefix, const char *imultilib,
|
||||
int stdinc, int cxx_stdinc, int verbose)
|
||||
{
|
||||
static const char *const lang_env_vars[] =
|
||||
{ "C_INCLUDE_PATH", "CPLUS_INCLUDE_PATH",
|
||||
@ -353,12 +385,33 @@ register_include_chains (cpp_reader *pfile, const char *sysroot,
|
||||
add_env_var_paths ("CPATH", BRACKET);
|
||||
add_env_var_paths (lang_env_vars[idx], SYSTEM);
|
||||
|
||||
target_c_incpath.extra_pre_includes (sysroot, iprefix, stdinc);
|
||||
|
||||
/* Finally chain on the standard directories. */
|
||||
if (stdinc)
|
||||
add_standard_paths (sysroot, iprefix, cxx_stdinc);
|
||||
add_standard_paths (sysroot, iprefix, imultilib, cxx_stdinc);
|
||||
|
||||
target_c_incpath.extra_includes (sysroot, iprefix, stdinc);
|
||||
|
||||
merge_include_chains (pfile, verbose);
|
||||
|
||||
cpp_set_include_chains (pfile, heads[QUOTE], heads[BRACKET],
|
||||
quote_ignores_source_dir);
|
||||
}
|
||||
#if !(defined TARGET_EXTRA_INCLUDES) || !(defined TARGET_EXTRA_PRE_INCLUDES)
|
||||
static void hook_void_charptr_charptr_int (const char *sysroot ATTRIBUTE_UNUSED,
|
||||
const char *iprefix ATTRIBUTE_UNUSED,
|
||||
int stdinc ATTRIBUTE_UNUSED)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_EXTRA_INCLUDES
|
||||
#define TARGET_EXTRA_INCLUDES hook_void_charptr_charptr_int
|
||||
#endif
|
||||
#ifndef TARGET_EXTRA_PRE_INCLUDES
|
||||
#define TARGET_EXTRA_PRE_INCLUDES hook_void_charptr_charptr_int
|
||||
#endif
|
||||
|
||||
struct target_c_incpath_s target_c_incpath = { TARGET_EXTRA_PRE_INCLUDES, TARGET_EXTRA_INCLUDES };
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Set up combined include path for the preprocessor.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
|
||||
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
|
||||
@ -13,11 +13,21 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
extern void split_quote_chain (void);
|
||||
extern void add_path (char *, int, int);
|
||||
extern void add_path (char *, int, int, bool);
|
||||
extern void register_include_chains (cpp_reader *, const char *,
|
||||
const char *, int, int, int);
|
||||
const char *, const char *,
|
||||
int, int, int);
|
||||
extern void add_cpp_dir_path (struct cpp_dir *, int);
|
||||
|
||||
struct target_c_incpath_s {
|
||||
/* Do extra includes processing. STDINC is false iff -nostdinc was given. */
|
||||
void (*extra_pre_includes) (const char *, const char *, int);
|
||||
void (*extra_includes) (const char *, const char *, int);
|
||||
};
|
||||
|
||||
extern struct target_c_incpath_s target_c_incpath;
|
||||
|
||||
enum { QUOTE = 0, BRACKET, SYSTEM, AFTER };
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Language-specific hook definitions for C front end.
|
||||
Copyright (C) 1991, 1995, 1997, 1998,
|
||||
1999, 2000, 2001, 2003 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
|
||||
#include "config.h"
|
||||
@ -30,127 +30,31 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "ggc.h"
|
||||
#include "langhooks.h"
|
||||
#include "langhooks-def.h"
|
||||
#include "tree-inline.h"
|
||||
#include "diagnostic.h"
|
||||
#include "c-pretty-print.h"
|
||||
|
||||
static void c_initialize_diagnostics (diagnostic_context *);
|
||||
#include "c-objc-common.h"
|
||||
#include "c-pragma.h"
|
||||
|
||||
enum c_language_kind c_language = clk_c;
|
||||
|
||||
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
|
||||
/* Lang hooks common to C and ObjC are declared in c-objc-common.h;
|
||||
consequently, there should be very few hooks below. */
|
||||
|
||||
#undef LANG_HOOKS_NAME
|
||||
#define LANG_HOOKS_NAME "GNU C"
|
||||
#undef LANG_HOOKS_INIT
|
||||
#define LANG_HOOKS_INIT c_objc_common_init
|
||||
#undef LANG_HOOKS_FINISH
|
||||
#define LANG_HOOKS_FINISH c_common_finish
|
||||
#undef LANG_HOOKS_INIT_OPTIONS
|
||||
#define LANG_HOOKS_INIT_OPTIONS c_common_init_options
|
||||
#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
|
||||
#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
|
||||
#undef LANG_HOOKS_HANDLE_OPTION
|
||||
#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
|
||||
#undef LANG_HOOKS_MISSING_ARGUMENT
|
||||
#define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument
|
||||
#undef LANG_HOOKS_POST_OPTIONS
|
||||
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
|
||||
#undef LANG_HOOKS_GET_ALIAS_SET
|
||||
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
|
||||
#undef LANG_HOOKS_SAFE_FROM_P
|
||||
#define LANG_HOOKS_SAFE_FROM_P c_safe_from_p
|
||||
#undef LANG_HOOKS_EXPAND_EXPR
|
||||
#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
|
||||
#undef LANG_HOOKS_MARK_ADDRESSABLE
|
||||
#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
|
||||
#undef LANG_HOOKS_PARSE_FILE
|
||||
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
|
||||
#undef LANG_HOOKS_TRUTHVALUE_CONVERSION
|
||||
#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion
|
||||
#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
|
||||
#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
|
||||
#undef LANG_HOOKS_UNSAFE_FOR_REEVAL
|
||||
#define LANG_HOOKS_UNSAFE_FOR_REEVAL c_common_unsafe_for_reeval
|
||||
#undef LANG_HOOKS_STATICP
|
||||
#define LANG_HOOKS_STATICP c_staticp
|
||||
#undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME
|
||||
#define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME c_static_assembler_name
|
||||
#undef LANG_HOOKS_NO_BODY_BLOCKS
|
||||
#define LANG_HOOKS_NO_BODY_BLOCKS true
|
||||
#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
|
||||
#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
|
||||
#undef LANG_HOOKS_PRINT_IDENTIFIER
|
||||
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
|
||||
#undef LANG_HOOKS_FUNCTION_ENTER_NESTED
|
||||
#define LANG_HOOKS_FUNCTION_ENTER_NESTED c_push_function_context
|
||||
#undef LANG_HOOKS_FUNCTION_LEAVE_NESTED
|
||||
#define LANG_HOOKS_FUNCTION_LEAVE_NESTED c_pop_function_context
|
||||
#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
|
||||
#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL c_dup_lang_specific_decl
|
||||
#undef LANG_HOOKS_DECL_UNINIT
|
||||
#define LANG_HOOKS_DECL_UNINIT c_decl_uninit
|
||||
|
||||
#undef LANG_HOOKS_RTL_EXPAND_STMT
|
||||
#define LANG_HOOKS_RTL_EXPAND_STMT expand_stmt
|
||||
|
||||
/* Attribute hooks. */
|
||||
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
|
||||
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
|
||||
#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
|
||||
#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
|
||||
|
||||
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
|
||||
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
|
||||
c_cannot_inline_tree_fn
|
||||
#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
|
||||
#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
|
||||
c_disregard_inline_limits
|
||||
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
|
||||
anon_aggr_type_p
|
||||
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
|
||||
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
|
||||
c_convert_parm_for_inlining
|
||||
#undef LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS
|
||||
#define LANG_HOOKS_TREE_INLINING_ESTIMATE_NUM_INSNS c_estimate_num_insns
|
||||
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
|
||||
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
|
||||
|
||||
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
|
||||
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION c_expand_body
|
||||
|
||||
#undef LANG_HOOKS_TYPE_FOR_MODE
|
||||
#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
|
||||
#undef LANG_HOOKS_TYPE_FOR_SIZE
|
||||
#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
|
||||
#undef LANG_HOOKS_SIGNED_TYPE
|
||||
#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
|
||||
#undef LANG_HOOKS_UNSIGNED_TYPE
|
||||
#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
|
||||
#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
|
||||
#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
|
||||
#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
|
||||
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
|
||||
#undef LANG_HOOKS_TYPE_PROMOTES_TO
|
||||
#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
|
||||
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
|
||||
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
|
||||
|
||||
#undef LANG_HOOKS_WRITE_GLOBALS
|
||||
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
|
||||
|
||||
/* ### When changing hooks, consider if ObjC needs changing too!! ### */
|
||||
|
||||
/* Each front end provides its own. */
|
||||
/* Each front end provides its own lang hook initializer. */
|
||||
const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
|
||||
|
||||
/* Tree code classes. */
|
||||
|
||||
#define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
|
||||
|
||||
const char tree_code_type[] = {
|
||||
const enum tree_code_class tree_code_type[] = {
|
||||
#include "tree.def"
|
||||
'x',
|
||||
tcc_exceptional,
|
||||
#include "c-common.def"
|
||||
};
|
||||
#undef DEFTREECODE
|
||||
@ -179,23 +83,11 @@ const char *const tree_code_name[] = {
|
||||
};
|
||||
#undef DEFTREECODE
|
||||
|
||||
/* Final processing of file-scope data. The Objective-C version of
|
||||
this function still does something. */
|
||||
void
|
||||
finish_file (void)
|
||||
{
|
||||
c_objc_common_finish_file ();
|
||||
}
|
||||
|
||||
static void
|
||||
c_initialize_diagnostics (diagnostic_context *context)
|
||||
{
|
||||
pretty_printer *base = context->printer;
|
||||
c_pretty_printer *pp = xmalloc (sizeof (c_pretty_printer));
|
||||
memcpy (pp_base (pp), base, sizeof (pretty_printer));
|
||||
pp_c_pretty_printer_init (pp);
|
||||
context->printer = (pretty_printer *) pp;
|
||||
|
||||
/* It is safe to free this object because it was previously malloc()'d. */
|
||||
free (base);
|
||||
}
|
||||
|
||||
#include "gtype-c.h"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Some code common to C and ObjC front ends.
|
||||
Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,8 +15,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -26,8 +26,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "rtl.h"
|
||||
#include "insn-config.h"
|
||||
#include "integrate.h"
|
||||
#include "expr.h"
|
||||
#include "c-tree.h"
|
||||
#include "c-pretty-print.h"
|
||||
#include "function.h"
|
||||
#include "flags.h"
|
||||
#include "toplev.h"
|
||||
@ -36,14 +36,14 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "varray.h"
|
||||
#include "ggc.h"
|
||||
#include "langhooks.h"
|
||||
#include "tree-mudflap.h"
|
||||
#include "target.h"
|
||||
#include "cgraph.h"
|
||||
#include "c-objc-common.h"
|
||||
|
||||
static bool c_tree_printer (pretty_printer *, text_info *);
|
||||
static tree start_cdtor (int);
|
||||
static void finish_cdtor (tree);
|
||||
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
|
||||
int, bool, bool, bool);
|
||||
|
||||
int
|
||||
bool
|
||||
c_missing_noreturn_ok_p (tree decl)
|
||||
{
|
||||
/* A missing noreturn is not ok for freestanding implementations and
|
||||
@ -69,7 +69,6 @@ int
|
||||
c_cannot_inline_tree_fn (tree *fnp)
|
||||
{
|
||||
tree fn = *fnp;
|
||||
tree t;
|
||||
bool do_warning = (warn_inline
|
||||
&& DECL_INLINE (fn)
|
||||
&& DECL_DECLARED_INLINE_P (fn)
|
||||
@ -79,50 +78,26 @@ c_cannot_inline_tree_fn (tree *fnp)
|
||||
&& lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
|
||||
{
|
||||
if (do_warning)
|
||||
warning ("%Jfunction '%F' can never be inlined because it "
|
||||
"is suppressed using -fno-inline", fn, fn);
|
||||
warning (OPT_Winline, "function %q+F can never be inlined because it "
|
||||
"is suppressed using -fno-inline", fn);
|
||||
goto cannot_inline;
|
||||
}
|
||||
|
||||
/* Don't auto-inline anything that might not be bound within
|
||||
this unit of translation. */
|
||||
if (!DECL_DECLARED_INLINE_P (fn) && !(*targetm.binds_local_p) (fn))
|
||||
if (!DECL_DECLARED_INLINE_P (fn) && !targetm.binds_local_p (fn))
|
||||
{
|
||||
if (do_warning)
|
||||
warning ("%Jfunction '%F' can never be inlined because it might not "
|
||||
"be bound within this unit of translation", fn, fn);
|
||||
warning (OPT_Winline, "function %q+F can never be inlined because it "
|
||||
"might not be bound within this unit of translation", fn);
|
||||
goto cannot_inline;
|
||||
}
|
||||
|
||||
if (! function_attribute_inlinable_p (fn))
|
||||
if (!function_attribute_inlinable_p (fn))
|
||||
{
|
||||
if (do_warning)
|
||||
warning ("%Jfunction '%F' can never be inlined because it uses "
|
||||
"attributes conflicting with inlining", fn, fn);
|
||||
goto cannot_inline;
|
||||
}
|
||||
|
||||
/* If a function has pending sizes, we must not defer its
|
||||
compilation, and we can't inline it as a tree. */
|
||||
if (fn == current_function_decl)
|
||||
{
|
||||
t = get_pending_sizes ();
|
||||
put_pending_sizes (t);
|
||||
|
||||
if (t)
|
||||
{
|
||||
if (do_warning)
|
||||
warning ("%Jfunction '%F' can never be inlined because it has "
|
||||
"pending sizes", fn, fn);
|
||||
goto cannot_inline;
|
||||
}
|
||||
}
|
||||
|
||||
if (DECL_LANG_SPECIFIC (fn)->pending_sizes)
|
||||
{
|
||||
if (do_warning)
|
||||
warning ("%Jfunction '%F' can never be inlined because it has "
|
||||
"pending sizes", fn, fn);
|
||||
warning (OPT_Winline, "function %q+F can never be inlined because it "
|
||||
"uses attributes conflicting with inlining", fn);
|
||||
goto cannot_inline;
|
||||
}
|
||||
|
||||
@ -150,24 +125,15 @@ c_warn_unused_global_decl (tree decl)
|
||||
bool
|
||||
c_objc_common_init (void)
|
||||
{
|
||||
static const enum tree_code stmt_codes[] = {
|
||||
c_common_stmt_codes
|
||||
};
|
||||
|
||||
INIT_STATEMENT_CODES (stmt_codes);
|
||||
|
||||
c_init_decl_processing ();
|
||||
|
||||
if (c_common_init () == false)
|
||||
return false;
|
||||
|
||||
lang_expand_decl_stmt = c_expand_decl_stmt;
|
||||
|
||||
/* These were not defined in the Objective-C front end, but I'm
|
||||
putting them here anyway. The diagnostic format decoder might
|
||||
want an enhanced ObjC implementation. */
|
||||
diagnostic_format_decoder (global_dc) = &c_tree_printer;
|
||||
lang_missing_noreturn_ok_p = &c_missing_noreturn_ok_p;
|
||||
|
||||
/* If still unspecified, make it match -std=c99
|
||||
(allowing for -pedantic-errors). */
|
||||
@ -182,102 +148,11 @@ c_objc_common_init (void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static tree
|
||||
start_cdtor (int method_type)
|
||||
{
|
||||
tree fnname = get_file_function_name (method_type);
|
||||
tree void_list_node_1 = build_tree_list (NULL_TREE, void_type_node);
|
||||
tree body;
|
||||
|
||||
start_function (void_list_node_1,
|
||||
build_nt (CALL_EXPR, fnname,
|
||||
tree_cons (NULL_TREE, NULL_TREE, void_list_node_1),
|
||||
NULL_TREE),
|
||||
NULL_TREE);
|
||||
store_parm_decls ();
|
||||
|
||||
current_function_cannot_inline
|
||||
= "static constructors and destructors cannot be inlined";
|
||||
|
||||
body = c_begin_compound_stmt ();
|
||||
|
||||
pushlevel (0);
|
||||
clear_last_expr ();
|
||||
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
|
||||
|
||||
return body;
|
||||
}
|
||||
|
||||
static void
|
||||
finish_cdtor (tree body)
|
||||
{
|
||||
tree scope;
|
||||
tree block;
|
||||
|
||||
scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
|
||||
block = poplevel (0, 0, 0);
|
||||
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block;
|
||||
SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block;
|
||||
|
||||
RECHAIN_STMTS (body, COMPOUND_BODY (body));
|
||||
|
||||
finish_function ();
|
||||
}
|
||||
|
||||
/* Called at end of parsing, but before end-of-file processing. */
|
||||
|
||||
void
|
||||
c_objc_common_finish_file (void)
|
||||
{
|
||||
if (pch_file)
|
||||
c_common_write_pch ();
|
||||
|
||||
/* If multiple translation units were built, copy information between
|
||||
them based on linkage rules. */
|
||||
merge_translation_unit_decls ();
|
||||
|
||||
cgraph_finalize_compilation_unit ();
|
||||
cgraph_optimize ();
|
||||
|
||||
if (static_ctors)
|
||||
{
|
||||
tree body = start_cdtor ('I');
|
||||
|
||||
for (; static_ctors; static_ctors = TREE_CHAIN (static_ctors))
|
||||
c_expand_expr_stmt (build_function_call (TREE_VALUE (static_ctors),
|
||||
NULL_TREE));
|
||||
|
||||
finish_cdtor (body);
|
||||
}
|
||||
|
||||
if (static_dtors)
|
||||
{
|
||||
tree body = start_cdtor ('D');
|
||||
|
||||
for (; static_dtors; static_dtors = TREE_CHAIN (static_dtors))
|
||||
c_expand_expr_stmt (build_function_call (TREE_VALUE (static_dtors),
|
||||
NULL_TREE));
|
||||
|
||||
finish_cdtor (body);
|
||||
}
|
||||
|
||||
{
|
||||
int flags;
|
||||
FILE *stream = dump_begin (TDI_all, &flags);
|
||||
|
||||
if (stream)
|
||||
{
|
||||
dump_node (getdecls (), flags & ~TDF_SLIM, stream);
|
||||
dump_end (TDI_all, stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Called during diagnostic message formatting process to print a
|
||||
source-level entity onto BUFFER. The meaning of the format specifiers
|
||||
is as follows:
|
||||
%D: a general decl,
|
||||
%E: An expression,
|
||||
%E: an identifier or expression,
|
||||
%F: a function declaration,
|
||||
%T: a type.
|
||||
|
||||
@ -286,30 +161,56 @@ c_objc_common_finish_file (void)
|
||||
Please notice when called, the `%' part was already skipped by the
|
||||
diagnostic machinery. */
|
||||
static bool
|
||||
c_tree_printer (pretty_printer *pp, text_info *text)
|
||||
c_tree_printer (pretty_printer *pp, text_info *text, const char *spec,
|
||||
int precision, bool wide, bool set_locus, bool hash)
|
||||
{
|
||||
tree t = va_arg (*text->args_ptr, tree);
|
||||
tree name;
|
||||
const char *n = "({anonymous})";
|
||||
c_pretty_printer *cpp = (c_pretty_printer *) pp;
|
||||
pp->padding = pp_none;
|
||||
|
||||
switch (*text->format_spec)
|
||||
if (precision != 0 || wide || hash)
|
||||
return false;
|
||||
|
||||
if (set_locus && text->locus)
|
||||
*text->locus = DECL_SOURCE_LOCATION (t);
|
||||
|
||||
switch (*spec)
|
||||
{
|
||||
case 'D':
|
||||
if (DECL_DEBUG_EXPR_IS_FROM (t) && DECL_DEBUG_EXPR (t))
|
||||
{
|
||||
t = DECL_DEBUG_EXPR (t);
|
||||
if (!DECL_P (t))
|
||||
{
|
||||
pp_c_expression (cpp, t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
|
||||
case 'F':
|
||||
if (DECL_NAME (t))
|
||||
n = (*lang_hooks.decl_printable_name) (t, 2);
|
||||
n = lang_hooks.decl_printable_name (t, 2);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (TREE_CODE (t) == TYPE_DECL)
|
||||
gcc_assert (TYPE_P (t));
|
||||
name = TYPE_NAME (t);
|
||||
|
||||
if (name && TREE_CODE (name) == TYPE_DECL)
|
||||
{
|
||||
if (DECL_NAME (t))
|
||||
n = (*lang_hooks.decl_printable_name) (t, 2);
|
||||
if (DECL_NAME (name))
|
||||
pp_string (cpp, lang_hooks.decl_printable_name (name, 2));
|
||||
else
|
||||
pp_type_id (cpp, t);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = TYPE_NAME (t);
|
||||
if (t)
|
||||
n = IDENTIFIER_POINTER (t);
|
||||
pp_type_id (cpp, t);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -317,13 +218,50 @@ c_tree_printer (pretty_printer *pp, text_info *text)
|
||||
if (TREE_CODE (t) == IDENTIFIER_NODE)
|
||||
n = IDENTIFIER_POINTER (t);
|
||||
else
|
||||
return false;
|
||||
{
|
||||
pp_expression (cpp, t);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
pp_string (pp, n);
|
||||
pp_string (cpp, n);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* In C and ObjC, all decls have "C" linkage. */
|
||||
bool
|
||||
has_c_linkage (tree decl ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
c_initialize_diagnostics (diagnostic_context *context)
|
||||
{
|
||||
pretty_printer *base = context->printer;
|
||||
c_pretty_printer *pp = XNEW (c_pretty_printer);
|
||||
memcpy (pp_base (pp), base, sizeof (pretty_printer));
|
||||
pp_c_pretty_printer_init (pp);
|
||||
context->printer = (pretty_printer *) pp;
|
||||
|
||||
/* It is safe to free this object because it was previously XNEW()'d. */
|
||||
XDELETE (base);
|
||||
}
|
||||
|
||||
int
|
||||
c_types_compatible_p (tree x, tree y)
|
||||
{
|
||||
return comptypes (TYPE_MAIN_VARIANT (x), TYPE_MAIN_VARIANT (y));
|
||||
}
|
||||
|
||||
/* Determine if the type is a vla type for the backend. */
|
||||
|
||||
bool
|
||||
c_vla_unspec_p (tree x, tree fn ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return c_vla_type_p (x);
|
||||
}
|
||||
|
143
contrib/gcc/c-objc-common.h
Normal file
143
contrib/gcc/c-objc-common.h
Normal file
@ -0,0 +1,143 @@
|
||||
/* Language hooks common to C and ObjC front ends.
|
||||
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Ziemowit Laski <zlaski@apple.com>
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_C_OBJC_COMMON
|
||||
#define GCC_C_OBJC_COMMON
|
||||
|
||||
/* In c-objc-common.c. */
|
||||
extern void c_initialize_diagnostics (diagnostic_context *);
|
||||
|
||||
/* Lang hooks that are shared between C and ObjC are defined here. Hooks
|
||||
specific to C or ObjC go in c-lang.c and objc/objc-lang.c, respectively. */
|
||||
|
||||
#undef LANG_HOOKS_IDENTIFIER_SIZE
|
||||
#define LANG_HOOKS_IDENTIFIER_SIZE C_SIZEOF_STRUCT_LANG_IDENTIFIER
|
||||
#undef LANG_HOOKS_FINISH
|
||||
#define LANG_HOOKS_FINISH c_common_finish
|
||||
#undef LANG_HOOKS_INIT_OPTIONS
|
||||
#define LANG_HOOKS_INIT_OPTIONS c_common_init_options
|
||||
#undef LANG_HOOKS_INITIALIZE_DIAGNOSTICS
|
||||
#define LANG_HOOKS_INITIALIZE_DIAGNOSTICS c_initialize_diagnostics
|
||||
#undef LANG_HOOKS_HANDLE_OPTION
|
||||
#define LANG_HOOKS_HANDLE_OPTION c_common_handle_option
|
||||
#undef LANG_HOOKS_MISSING_ARGUMENT
|
||||
#define LANG_HOOKS_MISSING_ARGUMENT c_common_missing_argument
|
||||
#undef LANG_HOOKS_POST_OPTIONS
|
||||
#define LANG_HOOKS_POST_OPTIONS c_common_post_options
|
||||
#undef LANG_HOOKS_GET_ALIAS_SET
|
||||
#define LANG_HOOKS_GET_ALIAS_SET c_common_get_alias_set
|
||||
#undef LANG_HOOKS_EXPAND_EXPR
|
||||
#define LANG_HOOKS_EXPAND_EXPR c_expand_expr
|
||||
#undef LANG_HOOKS_EXPAND_DECL
|
||||
#define LANG_HOOKS_EXPAND_DECL c_expand_decl
|
||||
#undef LANG_HOOKS_MARK_ADDRESSABLE
|
||||
#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable
|
||||
#undef LANG_HOOKS_PARSE_FILE
|
||||
#define LANG_HOOKS_PARSE_FILE c_common_parse_file
|
||||
#undef LANG_HOOKS_FINISH_INCOMPLETE_DECL
|
||||
#define LANG_HOOKS_FINISH_INCOMPLETE_DECL c_finish_incomplete_decl
|
||||
#undef LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS
|
||||
#define LANG_HOOKS_REDUCE_BIT_FIELD_OPERATIONS true
|
||||
#undef LANG_HOOKS_STATICP
|
||||
#define LANG_HOOKS_STATICP c_staticp
|
||||
#undef LANG_HOOKS_NO_BODY_BLOCKS
|
||||
#define LANG_HOOKS_NO_BODY_BLOCKS true
|
||||
#undef LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL
|
||||
#define LANG_HOOKS_WARN_UNUSED_GLOBAL_DECL c_warn_unused_global_decl
|
||||
#undef LANG_HOOKS_PRINT_IDENTIFIER
|
||||
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
|
||||
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
|
||||
#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
|
||||
#undef LANG_HOOKS_FUNCTION_ENTER_NESTED
|
||||
#define LANG_HOOKS_FUNCTION_ENTER_NESTED c_push_function_context
|
||||
#undef LANG_HOOKS_FUNCTION_LEAVE_NESTED
|
||||
#define LANG_HOOKS_FUNCTION_LEAVE_NESTED c_pop_function_context
|
||||
#undef LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P
|
||||
#define LANG_HOOKS_FUNCTION_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
|
||||
#undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL
|
||||
#define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL c_dup_lang_specific_decl
|
||||
|
||||
/* Attribute hooks. */
|
||||
#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE
|
||||
#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table
|
||||
#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE
|
||||
#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table
|
||||
|
||||
#undef LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN
|
||||
#define LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN \
|
||||
c_cannot_inline_tree_fn
|
||||
#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
|
||||
#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
|
||||
c_disregard_inline_limits
|
||||
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
|
||||
anon_aggr_type_p
|
||||
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
|
||||
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
|
||||
c_convert_parm_for_inlining
|
||||
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
|
||||
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
|
||||
|
||||
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
|
||||
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION c_expand_body
|
||||
|
||||
#undef LANG_HOOKS_TYPE_FOR_MODE
|
||||
#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode
|
||||
#undef LANG_HOOKS_TYPE_FOR_SIZE
|
||||
#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size
|
||||
#undef LANG_HOOKS_SIGNED_TYPE
|
||||
#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type
|
||||
#undef LANG_HOOKS_UNSIGNED_TYPE
|
||||
#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type
|
||||
#undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE
|
||||
#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type
|
||||
#undef LANG_HOOKS_INCOMPLETE_TYPE_ERROR
|
||||
#define LANG_HOOKS_INCOMPLETE_TYPE_ERROR c_incomplete_type_error
|
||||
#undef LANG_HOOKS_TYPE_PROMOTES_TO
|
||||
#define LANG_HOOKS_TYPE_PROMOTES_TO c_type_promotes_to
|
||||
#undef LANG_HOOKS_REGISTER_BUILTIN_TYPE
|
||||
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
|
||||
#undef LANG_HOOKS_TO_TARGET_CHARSET
|
||||
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
|
||||
#undef LANG_HOOKS_EXPR_TO_DECL
|
||||
#define LANG_HOOKS_EXPR_TO_DECL c_expr_to_decl
|
||||
|
||||
/* The C front end's scoping structure is very different from
|
||||
that expected by the language-independent code; it is best
|
||||
to disable getdecls.
|
||||
This means it must also provide its own write_globals. */
|
||||
|
||||
#undef LANG_HOOKS_GETDECLS
|
||||
#define LANG_HOOKS_GETDECLS lhd_return_null_tree_v
|
||||
#undef LANG_HOOKS_WRITE_GLOBALS
|
||||
#define LANG_HOOKS_WRITE_GLOBALS c_write_global_declarations
|
||||
|
||||
/* Hooks for tree gimplification. */
|
||||
#undef LANG_HOOKS_GIMPLIFY_EXPR
|
||||
#define LANG_HOOKS_GIMPLIFY_EXPR c_gimplify_expr
|
||||
|
||||
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
|
||||
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING c_omp_predetermined_sharing
|
||||
|
||||
#undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P
|
||||
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p
|
||||
|
||||
#endif /* GCC_C_OBJC_COMMON */
|
441
contrib/gcc/c-omp.c
Normal file
441
contrib/gcc/c-omp.c
Normal file
@ -0,0 +1,441 @@
|
||||
/* This file contains routines to construct GNU OpenMP constructs,
|
||||
called from parsing in the C and C++ front ends.
|
||||
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
Contributed by Richard Henderson <rth@redhat.com>,
|
||||
Diego Novillo <dnovillo@redhat.com>.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "function.h"
|
||||
#include "c-common.h"
|
||||
#include "toplev.h"
|
||||
#include "tree-gimple.h"
|
||||
#include "bitmap.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
|
||||
/* Complete a #pragma omp master construct. STMT is the structured-block
|
||||
that follows the pragma. */
|
||||
|
||||
tree
|
||||
c_finish_omp_master (tree stmt)
|
||||
{
|
||||
return add_stmt (build1 (OMP_MASTER, void_type_node, stmt));
|
||||
}
|
||||
|
||||
/* Complete a #pragma omp critical construct. STMT is the structured-block
|
||||
that follows the pragma, NAME is the identifier in the pragma, or null
|
||||
if it was omitted. */
|
||||
|
||||
tree
|
||||
c_finish_omp_critical (tree body, tree name)
|
||||
{
|
||||
tree stmt = make_node (OMP_CRITICAL);
|
||||
TREE_TYPE (stmt) = void_type_node;
|
||||
OMP_CRITICAL_BODY (stmt) = body;
|
||||
OMP_CRITICAL_NAME (stmt) = name;
|
||||
return add_stmt (stmt);
|
||||
}
|
||||
|
||||
/* Complete a #pragma omp ordered construct. STMT is the structured-block
|
||||
that follows the pragma. */
|
||||
|
||||
tree
|
||||
c_finish_omp_ordered (tree stmt)
|
||||
{
|
||||
return add_stmt (build1 (OMP_ORDERED, void_type_node, stmt));
|
||||
}
|
||||
|
||||
|
||||
/* Complete a #pragma omp barrier construct. */
|
||||
|
||||
void
|
||||
c_finish_omp_barrier (void)
|
||||
{
|
||||
tree x;
|
||||
|
||||
x = built_in_decls[BUILT_IN_GOMP_BARRIER];
|
||||
x = build_function_call_expr (x, NULL);
|
||||
add_stmt (x);
|
||||
}
|
||||
|
||||
|
||||
/* Complete a #pragma omp atomic construct. The expression to be
|
||||
implemented atomically is LHS code= RHS. The value returned is
|
||||
either error_mark_node (if the construct was erroneous) or an
|
||||
OMP_ATOMIC node which should be added to the current statement tree
|
||||
with add_stmt. */
|
||||
|
||||
tree
|
||||
c_finish_omp_atomic (enum tree_code code, tree lhs, tree rhs)
|
||||
{
|
||||
tree x, type, addr;
|
||||
|
||||
if (lhs == error_mark_node || rhs == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* ??? According to one reading of the OpenMP spec, complex type are
|
||||
supported, but there are no atomic stores for any architecture.
|
||||
But at least icc 9.0 doesn't support complex types here either.
|
||||
And lets not even talk about vector types... */
|
||||
type = TREE_TYPE (lhs);
|
||||
if (!INTEGRAL_TYPE_P (type)
|
||||
&& !POINTER_TYPE_P (type)
|
||||
&& !SCALAR_FLOAT_TYPE_P (type))
|
||||
{
|
||||
error ("invalid expression type for %<#pragma omp atomic%>");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* ??? Validate that rhs does not overlap lhs. */
|
||||
|
||||
/* Take and save the address of the lhs. From then on we'll reference it
|
||||
via indirection. */
|
||||
addr = build_unary_op (ADDR_EXPR, lhs, 0);
|
||||
if (addr == error_mark_node)
|
||||
return error_mark_node;
|
||||
addr = save_expr (addr);
|
||||
if (TREE_CODE (addr) != SAVE_EXPR
|
||||
&& (TREE_CODE (addr) != ADDR_EXPR
|
||||
|| TREE_CODE (TREE_OPERAND (addr, 0)) != VAR_DECL))
|
||||
{
|
||||
/* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize
|
||||
it even after unsharing function body. */
|
||||
tree var = create_tmp_var_raw (TREE_TYPE (addr), NULL);
|
||||
addr = build4 (TARGET_EXPR, TREE_TYPE (addr), var, addr, NULL, NULL);
|
||||
}
|
||||
lhs = build_indirect_ref (addr, NULL);
|
||||
|
||||
/* There are lots of warnings, errors, and conversions that need to happen
|
||||
in the course of interpreting a statement. Use the normal mechanisms
|
||||
to do this, and then take it apart again. */
|
||||
x = build_modify_expr (lhs, code, rhs);
|
||||
if (x == error_mark_node)
|
||||
return error_mark_node;
|
||||
gcc_assert (TREE_CODE (x) == MODIFY_EXPR);
|
||||
rhs = TREE_OPERAND (x, 1);
|
||||
|
||||
/* Punt the actual generation of atomic operations to common code. */
|
||||
return build2 (OMP_ATOMIC, void_type_node, addr, rhs);
|
||||
}
|
||||
|
||||
|
||||
/* Complete a #pragma omp flush construct. We don't do anything with the
|
||||
variable list that the syntax allows. */
|
||||
|
||||
void
|
||||
c_finish_omp_flush (void)
|
||||
{
|
||||
tree x;
|
||||
|
||||
x = built_in_decls[BUILT_IN_SYNCHRONIZE];
|
||||
x = build_function_call_expr (x, NULL);
|
||||
add_stmt (x);
|
||||
}
|
||||
|
||||
|
||||
/* Check and canonicalize #pragma omp for increment expression.
|
||||
Helper function for c_finish_omp_for. */
|
||||
|
||||
static tree
|
||||
check_omp_for_incr_expr (tree exp, tree decl)
|
||||
{
|
||||
tree t;
|
||||
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (exp))
|
||||
|| TYPE_PRECISION (TREE_TYPE (exp)) < TYPE_PRECISION (TREE_TYPE (decl)))
|
||||
return error_mark_node;
|
||||
|
||||
if (exp == decl)
|
||||
return build_int_cst (TREE_TYPE (exp), 0);
|
||||
|
||||
switch (TREE_CODE (exp))
|
||||
{
|
||||
case NOP_EXPR:
|
||||
t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
|
||||
if (t != error_mark_node)
|
||||
return fold_convert (TREE_TYPE (exp), t);
|
||||
break;
|
||||
case MINUS_EXPR:
|
||||
t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
|
||||
if (t != error_mark_node)
|
||||
return fold_build2 (MINUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
|
||||
break;
|
||||
case PLUS_EXPR:
|
||||
t = check_omp_for_incr_expr (TREE_OPERAND (exp, 0), decl);
|
||||
if (t != error_mark_node)
|
||||
return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), t, TREE_OPERAND (exp, 1));
|
||||
t = check_omp_for_incr_expr (TREE_OPERAND (exp, 1), decl);
|
||||
if (t != error_mark_node)
|
||||
return fold_build2 (PLUS_EXPR, TREE_TYPE (exp), TREE_OPERAND (exp, 0), t);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Validate and emit code for the OpenMP directive #pragma omp for.
|
||||
INIT, COND, INCR, BODY and PRE_BODY are the five basic elements
|
||||
of the loop (initialization expression, controlling predicate, increment
|
||||
expression, body of the loop and statements to go before the loop).
|
||||
DECL is the iteration variable. */
|
||||
|
||||
tree
|
||||
c_finish_omp_for (location_t locus, tree decl, tree init, tree cond,
|
||||
tree incr, tree body, tree pre_body)
|
||||
{
|
||||
location_t elocus = locus;
|
||||
bool fail = false;
|
||||
|
||||
if (EXPR_HAS_LOCATION (init))
|
||||
elocus = EXPR_LOCATION (init);
|
||||
|
||||
/* Validate the iteration variable. */
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)))
|
||||
{
|
||||
error ("%Hinvalid type for iteration variable %qE", &elocus, decl);
|
||||
fail = true;
|
||||
}
|
||||
if (TYPE_UNSIGNED (TREE_TYPE (decl)))
|
||||
warning (0, "%Hiteration variable %qE is unsigned", &elocus, decl);
|
||||
|
||||
/* In the case of "for (int i = 0...)", init will be a decl. It should
|
||||
have a DECL_INITIAL that we can turn into an assignment. */
|
||||
if (init == decl)
|
||||
{
|
||||
elocus = DECL_SOURCE_LOCATION (decl);
|
||||
|
||||
init = DECL_INITIAL (decl);
|
||||
if (init == NULL)
|
||||
{
|
||||
error ("%H%qE is not initialized", &elocus, decl);
|
||||
init = integer_zero_node;
|
||||
fail = true;
|
||||
}
|
||||
|
||||
init = build_modify_expr (decl, NOP_EXPR, init);
|
||||
SET_EXPR_LOCATION (init, elocus);
|
||||
}
|
||||
gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
|
||||
gcc_assert (TREE_OPERAND (init, 0) == decl);
|
||||
|
||||
if (cond == NULL_TREE)
|
||||
{
|
||||
error ("%Hmissing controlling predicate", &elocus);
|
||||
fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool cond_ok = false;
|
||||
|
||||
if (EXPR_HAS_LOCATION (cond))
|
||||
elocus = EXPR_LOCATION (cond);
|
||||
|
||||
if (TREE_CODE (cond) == LT_EXPR
|
||||
|| TREE_CODE (cond) == LE_EXPR
|
||||
|| TREE_CODE (cond) == GT_EXPR
|
||||
|| TREE_CODE (cond) == GE_EXPR)
|
||||
{
|
||||
tree op0 = TREE_OPERAND (cond, 0);
|
||||
tree op1 = TREE_OPERAND (cond, 1);
|
||||
|
||||
/* 2.5.1. The comparison in the condition is computed in the type
|
||||
of DECL, otherwise the behavior is undefined.
|
||||
|
||||
For example:
|
||||
long n; int i;
|
||||
i < n;
|
||||
|
||||
according to ISO will be evaluated as:
|
||||
(long)i < n;
|
||||
|
||||
We want to force:
|
||||
i < (int)n; */
|
||||
if (TREE_CODE (op0) == NOP_EXPR
|
||||
&& decl == TREE_OPERAND (op0, 0))
|
||||
{
|
||||
TREE_OPERAND (cond, 0) = TREE_OPERAND (op0, 0);
|
||||
TREE_OPERAND (cond, 1) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
|
||||
TREE_OPERAND (cond, 1));
|
||||
}
|
||||
else if (TREE_CODE (op1) == NOP_EXPR
|
||||
&& decl == TREE_OPERAND (op1, 0))
|
||||
{
|
||||
TREE_OPERAND (cond, 1) = TREE_OPERAND (op1, 0);
|
||||
TREE_OPERAND (cond, 0) = fold_build1 (NOP_EXPR, TREE_TYPE (decl),
|
||||
TREE_OPERAND (cond, 0));
|
||||
}
|
||||
|
||||
if (decl == TREE_OPERAND (cond, 0))
|
||||
cond_ok = true;
|
||||
else if (decl == TREE_OPERAND (cond, 1))
|
||||
{
|
||||
TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
|
||||
TREE_OPERAND (cond, 1) = TREE_OPERAND (cond, 0);
|
||||
TREE_OPERAND (cond, 0) = decl;
|
||||
cond_ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cond_ok)
|
||||
{
|
||||
error ("%Hinvalid controlling predicate", &elocus);
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (incr == NULL_TREE)
|
||||
{
|
||||
error ("%Hmissing increment expression", &elocus);
|
||||
fail = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool incr_ok = false;
|
||||
|
||||
if (EXPR_HAS_LOCATION (incr))
|
||||
elocus = EXPR_LOCATION (incr);
|
||||
|
||||
/* Check all the valid increment expressions: v++, v--, ++v, --v,
|
||||
v = v + incr, v = incr + v and v = v - incr. */
|
||||
switch (TREE_CODE (incr))
|
||||
{
|
||||
case POSTINCREMENT_EXPR:
|
||||
case PREINCREMENT_EXPR:
|
||||
case POSTDECREMENT_EXPR:
|
||||
case PREDECREMENT_EXPR:
|
||||
incr_ok = (TREE_OPERAND (incr, 0) == decl);
|
||||
break;
|
||||
|
||||
case MODIFY_EXPR:
|
||||
if (TREE_OPERAND (incr, 0) != decl)
|
||||
break;
|
||||
if (TREE_OPERAND (incr, 1) == decl)
|
||||
break;
|
||||
if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR
|
||||
&& (TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl
|
||||
|| TREE_OPERAND (TREE_OPERAND (incr, 1), 1) == decl))
|
||||
incr_ok = true;
|
||||
else if (TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR
|
||||
&& TREE_OPERAND (TREE_OPERAND (incr, 1), 0) == decl)
|
||||
incr_ok = true;
|
||||
else
|
||||
{
|
||||
tree t = check_omp_for_incr_expr (TREE_OPERAND (incr, 1), decl);
|
||||
if (t != error_mark_node)
|
||||
{
|
||||
incr_ok = true;
|
||||
t = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, t);
|
||||
incr = build2 (MODIFY_EXPR, void_type_node, decl, t);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!incr_ok)
|
||||
{
|
||||
error ("%Hinvalid increment expression", &elocus);
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail)
|
||||
return NULL;
|
||||
else
|
||||
{
|
||||
tree t = make_node (OMP_FOR);
|
||||
|
||||
TREE_TYPE (t) = void_type_node;
|
||||
OMP_FOR_INIT (t) = init;
|
||||
OMP_FOR_COND (t) = cond;
|
||||
OMP_FOR_INCR (t) = incr;
|
||||
OMP_FOR_BODY (t) = body;
|
||||
OMP_FOR_PRE_BODY (t) = pre_body;
|
||||
|
||||
SET_EXPR_LOCATION (t, locus);
|
||||
return add_stmt (t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Divide CLAUSES into two lists: those that apply to a parallel construct,
|
||||
and those that apply to a work-sharing construct. Place the results in
|
||||
*PAR_CLAUSES and *WS_CLAUSES respectively. In addition, add a nowait
|
||||
clause to the work-sharing list. */
|
||||
|
||||
void
|
||||
c_split_parallel_clauses (tree clauses, tree *par_clauses, tree *ws_clauses)
|
||||
{
|
||||
tree next;
|
||||
|
||||
*par_clauses = NULL;
|
||||
*ws_clauses = build_omp_clause (OMP_CLAUSE_NOWAIT);
|
||||
|
||||
for (; clauses ; clauses = next)
|
||||
{
|
||||
next = OMP_CLAUSE_CHAIN (clauses);
|
||||
|
||||
switch (OMP_CLAUSE_CODE (clauses))
|
||||
{
|
||||
case OMP_CLAUSE_PRIVATE:
|
||||
case OMP_CLAUSE_SHARED:
|
||||
case OMP_CLAUSE_FIRSTPRIVATE:
|
||||
case OMP_CLAUSE_LASTPRIVATE:
|
||||
case OMP_CLAUSE_REDUCTION:
|
||||
case OMP_CLAUSE_COPYIN:
|
||||
case OMP_CLAUSE_IF:
|
||||
case OMP_CLAUSE_NUM_THREADS:
|
||||
case OMP_CLAUSE_DEFAULT:
|
||||
OMP_CLAUSE_CHAIN (clauses) = *par_clauses;
|
||||
*par_clauses = clauses;
|
||||
break;
|
||||
|
||||
case OMP_CLAUSE_SCHEDULE:
|
||||
case OMP_CLAUSE_ORDERED:
|
||||
OMP_CLAUSE_CHAIN (clauses) = *ws_clauses;
|
||||
*ws_clauses = clauses;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* True if OpenMP sharing attribute of DECL is predetermined. */
|
||||
|
||||
enum omp_clause_default_kind
|
||||
c_omp_predetermined_sharing (tree decl)
|
||||
{
|
||||
/* Variables with const-qualified type having no mutable member
|
||||
are predetermined shared. */
|
||||
if (TREE_READONLY (decl))
|
||||
return OMP_CLAUSE_DEFAULT_SHARED;
|
||||
|
||||
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
|
||||
}
|
7868
contrib/gcc/c-parser.c
Normal file
7868
contrib/gcc/c-parser.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Precompiled header implementation for the C languages.
|
||||
Copyright (C) 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,8 +15,8 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -35,37 +35,41 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "hosthooks.h"
|
||||
#include "target.h"
|
||||
|
||||
/* This structure is read very early when validating the PCH, and
|
||||
might be read for a PCH which is for a completely different compiler
|
||||
for a different operating system. Thus, it should really only contain
|
||||
'unsigned char' entries, at least in the initial entries.
|
||||
/* This is a list of flag variables that must match exactly, and their
|
||||
names for the error message. The possible values for *flag_var must
|
||||
fit in a 'signed char'. */
|
||||
|
||||
If you add or change entries before version_length, you should increase
|
||||
the version number in get_ident().
|
||||
static const struct c_pch_matching
|
||||
{
|
||||
int *flag_var;
|
||||
const char *flag_name;
|
||||
} pch_matching[] = {
|
||||
{ &flag_exceptions, "-fexceptions" },
|
||||
{ &flag_unit_at_a_time, "-funit-at-a-time" }
|
||||
};
|
||||
|
||||
There are a bunch of fields named *_length; those are lengths of data that
|
||||
follows this structure in the same order as the fields in the structure.
|
||||
enum {
|
||||
MATCH_SIZE = ARRAY_SIZE (pch_matching)
|
||||
};
|
||||
|
||||
The flags_info field is used to verify that certain flags settings that
|
||||
have to be the same during the compilation of the PCH and a compilation
|
||||
using the PCH are indeed the same. */
|
||||
/* The value of the checksum in the dummy compiler that is actually
|
||||
checksummed. That compiler should never be run. */
|
||||
static const char no_checksum[16] = { 0 };
|
||||
|
||||
/* Information about flags and suchlike that affect PCH validity.
|
||||
|
||||
Before this structure is read, both an initial 8-character identification
|
||||
string, and a 16-byte checksum, have been read and validated. */
|
||||
|
||||
struct c_pch_validity
|
||||
{
|
||||
unsigned char host_machine_length;
|
||||
unsigned char target_machine_length;
|
||||
unsigned char version_length;
|
||||
unsigned char debug_info_type;
|
||||
unsigned int flags_info;
|
||||
signed char match[MATCH_SIZE];
|
||||
void (*pch_init) (void);
|
||||
size_t target_data_length;
|
||||
};
|
||||
|
||||
/* If -funit-at-a-time is set, we require that it was also set during the
|
||||
compilation of the PCH we may be using. */
|
||||
#define FLAG_UNIT_AT_A_TIME_SET 1 << 0
|
||||
|
||||
struct c_pch_header
|
||||
struct c_pch_header
|
||||
{
|
||||
unsigned long asm_size;
|
||||
};
|
||||
@ -78,10 +82,6 @@ static FILE *pch_outfile;
|
||||
/* The position in the assembler output file when pch_init was called. */
|
||||
static long asm_file_startpos;
|
||||
|
||||
/* The host and target machines. */
|
||||
static const char host_machine[] = HOST_MACHINE;
|
||||
static const char target_machine[] = TARGET_MACHINE;
|
||||
|
||||
static const char *get_ident (void);
|
||||
|
||||
/* Compute an appropriate 8-byte magic number for the PCH file, so that
|
||||
@ -90,20 +90,22 @@ static const char *get_ident (void);
|
||||
format. */
|
||||
|
||||
static const char *
|
||||
get_ident(void)
|
||||
get_ident (void)
|
||||
{
|
||||
static char result[IDENT_LENGTH];
|
||||
static const char template[IDENT_LENGTH] = "gpch.012";
|
||||
static const char template[IDENT_LENGTH] = "gpch.013";
|
||||
static const char c_language_chars[] = "Co+O";
|
||||
|
||||
|
||||
memcpy (result, template, IDENT_LENGTH);
|
||||
result[4] = c_language_chars[c_language];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Prepare to write a PCH file. This is called at the start of
|
||||
compilation. */
|
||||
/* Prepare to write a PCH file, if one is being written. This is
|
||||
called at the start of compilation.
|
||||
|
||||
Also, print out the executable checksum if -fverbose-asm is in effect. */
|
||||
|
||||
void
|
||||
pch_init (void)
|
||||
@ -112,50 +114,55 @@ pch_init (void)
|
||||
struct c_pch_validity v;
|
||||
void *target_validity;
|
||||
static const char partial_pch[IDENT_LENGTH] = "gpcWrite";
|
||||
unsigned int current_flags_info = 0;
|
||||
|
||||
if (! pch_file)
|
||||
return;
|
||||
|
||||
if (flag_unit_at_a_time)
|
||||
current_flags_info |= FLAG_UNIT_AT_A_TIME_SET;
|
||||
#ifdef ASM_COMMENT_START
|
||||
if (flag_verbose_asm)
|
||||
{
|
||||
fprintf (asm_out_file, "%s ", ASM_COMMENT_START);
|
||||
c_common_print_pch_checksum (asm_out_file);
|
||||
fputc ('\n', asm_out_file);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!pch_file)
|
||||
return;
|
||||
|
||||
f = fopen (pch_file, "w+b");
|
||||
if (f == NULL)
|
||||
fatal_error ("can't create precompiled header %s: %m", pch_file);
|
||||
fatal_error ("can%'t create precompiled header %s: %m", pch_file);
|
||||
pch_outfile = f;
|
||||
|
||||
if (strlen (host_machine) > 255 || strlen (target_machine) > 255
|
||||
|| strlen (version_string) > 255)
|
||||
abort ();
|
||||
|
||||
v.host_machine_length = strlen (host_machine);
|
||||
v.target_machine_length = strlen (target_machine);
|
||||
v.version_length = strlen (version_string);
|
||||
|
||||
gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
|
||||
|
||||
v.debug_info_type = write_symbols;
|
||||
v.flags_info = current_flags_info;
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < MATCH_SIZE; i++)
|
||||
{
|
||||
v.match[i] = *pch_matching[i].flag_var;
|
||||
gcc_assert (v.match[i] == *pch_matching[i].flag_var);
|
||||
}
|
||||
}
|
||||
v.pch_init = &pch_init;
|
||||
target_validity = targetm.get_pch_validity (&v.target_data_length);
|
||||
|
||||
|
||||
if (fwrite (partial_pch, IDENT_LENGTH, 1, f) != 1
|
||||
|| fwrite (executable_checksum, 16, 1, f) != 1
|
||||
|| fwrite (&v, sizeof (v), 1, f) != 1
|
||||
|| fwrite (host_machine, v.host_machine_length, 1, f) != 1
|
||||
|| fwrite (target_machine, v.target_machine_length, 1, f) != 1
|
||||
|| fwrite (version_string, v.version_length, 1, f) != 1
|
||||
|| fwrite (target_validity, v.target_data_length, 1, f) != 1)
|
||||
fatal_error ("can't write to %s: %m", pch_file);
|
||||
fatal_error ("can%'t write to %s: %m", pch_file);
|
||||
|
||||
/* We need to be able to re-read the output. */
|
||||
/* The driver always provides a valid -o option. */
|
||||
if (asm_file_name == NULL
|
||||
|| strcmp (asm_file_name, "-") == 0)
|
||||
fatal_error ("`%s' is not a valid output file", asm_file_name);
|
||||
|
||||
fatal_error ("%qs is not a valid output file", asm_file_name);
|
||||
|
||||
asm_file_startpos = ftell (asm_out_file);
|
||||
|
||||
|
||||
/* Let the debugging format deal with the PCHness. */
|
||||
(*debug_hooks->handle_pch) (0);
|
||||
|
||||
|
||||
cpp_save_state (parse_in, f);
|
||||
}
|
||||
|
||||
@ -176,15 +183,14 @@ c_common_write_pch (void)
|
||||
|
||||
asm_file_end = ftell (asm_out_file);
|
||||
h.asm_size = asm_file_end - asm_file_startpos;
|
||||
|
||||
|
||||
if (fwrite (&h, sizeof (h), 1, pch_outfile) != 1)
|
||||
fatal_error ("can't write %s: %m", pch_file);
|
||||
|
||||
buf = xmalloc (16384);
|
||||
fflush (asm_out_file);
|
||||
fatal_error ("can%'t write %s: %m", pch_file);
|
||||
|
||||
buf = XNEWVEC (char, 16384);
|
||||
|
||||
if (fseek (asm_out_file, asm_file_startpos, SEEK_SET) != 0)
|
||||
fatal_error ("can't seek in %s: %m", asm_file_name);
|
||||
fatal_error ("can%'t seek in %s: %m", asm_file_name);
|
||||
|
||||
for (written = asm_file_startpos; written < asm_file_end; )
|
||||
{
|
||||
@ -192,21 +198,23 @@ c_common_write_pch (void)
|
||||
if (size > 16384)
|
||||
size = 16384;
|
||||
if (fread (buf, size, 1, asm_out_file) != 1)
|
||||
fatal_error ("can't read %s: %m", asm_file_name);
|
||||
fatal_error ("can%'t read %s: %m", asm_file_name);
|
||||
if (fwrite (buf, size, 1, pch_outfile) != 1)
|
||||
fatal_error ("can't write %s: %m", pch_file);
|
||||
fatal_error ("can%'t write %s: %m", pch_file);
|
||||
written += size;
|
||||
}
|
||||
free (buf);
|
||||
/* asm_out_file can be written afterwards, so must be flushed first. */
|
||||
fflush (asm_out_file);
|
||||
/* asm_out_file can be written afterwards, so fseek to clear
|
||||
_IOREAD flag. */
|
||||
if (fseek (asm_out_file, 0, SEEK_END) != 0)
|
||||
fatal_error ("can%'t seek in %s: %m", asm_file_name);
|
||||
|
||||
gt_pch_save (pch_outfile);
|
||||
cpp_write_pch_state (parse_in, pch_outfile);
|
||||
|
||||
if (fseek (pch_outfile, 0, SEEK_SET) != 0
|
||||
|| fwrite (get_ident (), IDENT_LENGTH, 1, pch_outfile) != 1)
|
||||
fatal_error ("can't write %s: %m", pch_file);
|
||||
fatal_error ("can%'t write %s: %m", pch_file);
|
||||
|
||||
fclose (pch_outfile);
|
||||
}
|
||||
@ -221,26 +229,25 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
{
|
||||
int sizeread;
|
||||
int result;
|
||||
char ident[IDENT_LENGTH];
|
||||
char short_strings[256 * 3];
|
||||
int strings_length;
|
||||
char ident[IDENT_LENGTH + 16];
|
||||
const char *pch_ident;
|
||||
struct c_pch_validity v;
|
||||
unsigned int current_flags_info = 0;
|
||||
|
||||
if (flag_unit_at_a_time)
|
||||
current_flags_info |= FLAG_UNIT_AT_A_TIME_SET;
|
||||
|
||||
/* Perform a quick test of whether this is a valid
|
||||
precompiled header for the current language
|
||||
and with the current flag settings. */
|
||||
precompiled header for the current language. */
|
||||
|
||||
sizeread = read (fd, ident, IDENT_LENGTH);
|
||||
gcc_assert (memcmp (executable_checksum, no_checksum, 16) != 0);
|
||||
|
||||
sizeread = read (fd, ident, IDENT_LENGTH + 16);
|
||||
if (sizeread == -1)
|
||||
fatal_error ("can't read %s: %m", name);
|
||||
else if (sizeread != IDENT_LENGTH)
|
||||
return 2;
|
||||
|
||||
fatal_error ("can%'t read %s: %m", name);
|
||||
else if (sizeread != IDENT_LENGTH + 16)
|
||||
{
|
||||
cpp_error (pfile, CPP_DL_WARNING, "%s: too short to be a PCH file",
|
||||
name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
pch_ident = get_ident();
|
||||
if (memcmp (ident, pch_ident, IDENT_LENGTH) != 0)
|
||||
{
|
||||
@ -249,71 +256,31 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
if (memcmp (ident, pch_ident, 5) == 0)
|
||||
/* It's a PCH, for the right language, but has the wrong version.
|
||||
*/
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: not compatible with this GCC version", name);
|
||||
else if (memcmp (ident, pch_ident, 4) == 0)
|
||||
/* It's a PCH for the wrong language. */
|
||||
cpp_error (pfile, CPP_DL_WARNING, "%s: not for %s", name,
|
||||
lang_hooks.name);
|
||||
else
|
||||
else
|
||||
/* Not any kind of PCH. */
|
||||
cpp_error (pfile, CPP_DL_WARNING, "%s: not a PCH file", name);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
if (memcmp (ident + IDENT_LENGTH, executable_checksum, 16) != 0)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created by a different GCC executable", name);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* At this point, we know it's a PCH file, so it ought to be long enough
|
||||
that we can read a c_pch_validity structure. */
|
||||
/* At this point, we know it's a PCH file created by this
|
||||
executable, so it ought to be long enough that we can read a
|
||||
c_pch_validity structure. */
|
||||
if (read (fd, &v, sizeof (v)) != sizeof (v))
|
||||
fatal_error ("can't read %s: %m", name);
|
||||
|
||||
strings_length = (v.host_machine_length + v.target_machine_length
|
||||
+ v.version_length);
|
||||
if (read (fd, short_strings, strings_length) != strings_length)
|
||||
fatal_error ("can't read %s: %m", name);
|
||||
if (v.host_machine_length != strlen (host_machine)
|
||||
|| memcmp (host_machine, short_strings, strlen (host_machine)) != 0)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created on host `%.*s', but used on host `%s'", name,
|
||||
v.host_machine_length, short_strings, host_machine);
|
||||
return 2;
|
||||
}
|
||||
if (v.target_machine_length != strlen (target_machine)
|
||||
|| memcmp (target_machine, short_strings + v.host_machine_length,
|
||||
strlen (target_machine)) != 0)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created for target `%.*s', but used for target `%s'",
|
||||
name, v.target_machine_length,
|
||||
short_strings + v.host_machine_length, target_machine);
|
||||
return 2;
|
||||
}
|
||||
if (v.version_length != strlen (version_string)
|
||||
|| memcmp (version_string,
|
||||
(short_strings + v.host_machine_length
|
||||
+ v.target_machine_length),
|
||||
v.version_length) != 0)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created by version `%.*s', but this is version `%s'",
|
||||
name, v.version_length,
|
||||
(short_strings + v.host_machine_length
|
||||
+ v.target_machine_length),
|
||||
version_string);
|
||||
return 2;
|
||||
}
|
||||
if (v.flags_info != current_flags_info)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created using different flags",
|
||||
name);
|
||||
return 2;
|
||||
}
|
||||
fatal_error ("can%'t read %s: %m", name);
|
||||
|
||||
/* The allowable debug info combinations are that either the PCH file
|
||||
was built with the same as is being used now, or the PCH file was
|
||||
@ -322,21 +289,37 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
&& write_symbols != NO_DEBUG)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: created with -g%s, but used with -g%s", name,
|
||||
debug_type_names[v.debug_info_type],
|
||||
debug_type_names[write_symbols]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* Check flags that must match exactly. */
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < MATCH_SIZE; i++)
|
||||
if (*pch_matching[i].flag_var != v.match[i])
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: settings for %s do not match", name,
|
||||
pch_matching[i].flag_name);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the text segment was not loaded at the same address as it was
|
||||
when the PCH file was created, function pointers loaded from the
|
||||
PCH will not be valid. We could in theory remap all the function
|
||||
pointers, but no support for that exists at present. */
|
||||
pointers, but no support for that exists at present.
|
||||
Since we have the same executable, it should only be necessary to
|
||||
check one function. */
|
||||
if (v.pch_init != &pch_init)
|
||||
{
|
||||
if (cpp_get_options (pfile)->warn_invalid_pch)
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
cpp_error (pfile, CPP_DL_WARNING,
|
||||
"%s: had text segment at different address", name);
|
||||
return 2;
|
||||
}
|
||||
@ -345,10 +328,10 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
{
|
||||
void *this_file_data = xmalloc (v.target_data_length);
|
||||
const char *msg;
|
||||
|
||||
|
||||
if ((size_t) read (fd, this_file_data, v.target_data_length)
|
||||
!= v.target_data_length)
|
||||
fatal_error ("can't read %s: %m", name);
|
||||
fatal_error ("can%'t read %s: %m", name);
|
||||
msg = targetm.pch_valid_p (this_file_data, v.target_data_length);
|
||||
free (this_file_data);
|
||||
if (msg != NULL)
|
||||
@ -361,7 +344,7 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
|
||||
/* Check the preprocessor macros are the same as when the PCH was
|
||||
generated. */
|
||||
|
||||
|
||||
result = cpp_valid_state (pfile, name, fd);
|
||||
if (result == -1)
|
||||
return 2;
|
||||
@ -369,6 +352,10 @@ c_common_valid_pch (cpp_reader *pfile, const char *name, int fd)
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
/* If non-NULL, this function is called after a precompile header file
|
||||
is loaded. */
|
||||
void (*lang_post_pch_load) (void);
|
||||
|
||||
/* Load in the PCH file NAME, open on FD. It was originally searched for
|
||||
by ORIG_NAME. */
|
||||
|
||||
@ -378,10 +365,8 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
|
||||
{
|
||||
FILE *f;
|
||||
struct c_pch_header h;
|
||||
char *buf;
|
||||
unsigned long written;
|
||||
struct save_macro_data *smd;
|
||||
|
||||
|
||||
f = fdopen (fd, "rb");
|
||||
if (f == NULL)
|
||||
{
|
||||
@ -397,18 +382,30 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
|
||||
return;
|
||||
}
|
||||
|
||||
buf = xmalloc (16384);
|
||||
for (written = 0; written < h.asm_size; )
|
||||
if (!flag_preprocess_only)
|
||||
{
|
||||
long size = h.asm_size - written;
|
||||
if (size > 16384)
|
||||
size = 16384;
|
||||
if (fread (buf, size, 1, f) != 1
|
||||
|| fwrite (buf, size, 1, asm_out_file) != 1)
|
||||
cpp_errno (pfile, CPP_DL_ERROR, "reading");
|
||||
written += size;
|
||||
unsigned long written;
|
||||
char * buf = XNEWVEC (char, 16384);
|
||||
|
||||
for (written = 0; written < h.asm_size; )
|
||||
{
|
||||
long size = h.asm_size - written;
|
||||
if (size > 16384)
|
||||
size = 16384;
|
||||
if (fread (buf, size, 1, f) != 1
|
||||
|| fwrite (buf, size, 1, asm_out_file) != 1)
|
||||
cpp_errno (pfile, CPP_DL_ERROR, "reading");
|
||||
written += size;
|
||||
}
|
||||
free (buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we're preprocessing, don't write to a NULL
|
||||
asm_out_file. */
|
||||
if (fseek (f, h.asm_size, SEEK_CUR) != 0)
|
||||
cpp_errno (pfile, CPP_DL_ERROR, "seeking");
|
||||
}
|
||||
free (buf);
|
||||
|
||||
cpp_prepare_state (pfile, &smd);
|
||||
|
||||
@ -418,6 +415,11 @@ c_common_read_pch (cpp_reader *pfile, const char *name,
|
||||
return;
|
||||
|
||||
fclose (f);
|
||||
|
||||
/* Give the front end a chance to take action after a PCH file has
|
||||
been loaded. */
|
||||
if (lang_post_pch_load)
|
||||
(*lang_post_pch_load) ();
|
||||
}
|
||||
|
||||
/* Indicate that no more PCH files should be read. */
|
||||
@ -431,3 +433,49 @@ c_common_no_more_pch (void)
|
||||
host_hooks.gt_pch_use_address (NULL, 0, -1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle #pragma GCC pch_preprocess, to load in the PCH file. */
|
||||
|
||||
#ifndef O_BINARY
|
||||
# define O_BINARY 0
|
||||
#endif
|
||||
|
||||
void
|
||||
c_common_pch_pragma (cpp_reader *pfile, const char *name)
|
||||
{
|
||||
int fd;
|
||||
|
||||
if (!cpp_get_options (pfile)->preprocessed)
|
||||
{
|
||||
error ("pch_preprocess pragma should only be used with -fpreprocessed");
|
||||
inform ("use #include instead");
|
||||
return;
|
||||
}
|
||||
|
||||
fd = open (name, O_RDONLY | O_BINARY, 0666);
|
||||
if (fd == -1)
|
||||
fatal_error ("%s: couldn%'t open PCH file: %m", name);
|
||||
|
||||
if (c_common_valid_pch (pfile, name, fd) != 1)
|
||||
{
|
||||
if (!cpp_get_options (pfile)->warn_invalid_pch)
|
||||
inform ("use -Winvalid-pch for more information");
|
||||
fatal_error ("%s: PCH file was invalid", name);
|
||||
}
|
||||
|
||||
c_common_read_pch (pfile, name, fd, name);
|
||||
|
||||
close (fd);
|
||||
}
|
||||
|
||||
/* Print out executable_checksum[]. */
|
||||
|
||||
void
|
||||
c_common_print_pch_checksum (FILE *f)
|
||||
{
|
||||
int i;
|
||||
fputs ("Compiler executable checksum: ", f);
|
||||
for (i = 0; i < 16; i++)
|
||||
fprintf (f, "%02x", executable_checksum[i]);
|
||||
putc ('\n', f);
|
||||
}
|
||||
|
@ -15,14 +15,14 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "cpplib.h"
|
||||
#include "cpphash.h"
|
||||
#include "../libcpp/internal.h"
|
||||
#include "tree.h"
|
||||
#include "c-common.h" /* For flags. */
|
||||
#include "c-pragma.h" /* For parse_in. */
|
||||
@ -32,11 +32,11 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
static struct
|
||||
{
|
||||
FILE *outf; /* Stream to write to. */
|
||||
const struct line_map *map; /* Logical to physical line mappings. */
|
||||
const cpp_token *prev; /* Previous token. */
|
||||
const cpp_token *source; /* Source token for spacing. */
|
||||
fileline line; /* Line currently being written. */
|
||||
int src_line; /* Line number currently being written. */
|
||||
unsigned char printed; /* Nonzero if something output at line. */
|
||||
bool first_time; /* pp_file_change hasn't been called yet. */
|
||||
} print;
|
||||
|
||||
/* General output routines. */
|
||||
@ -45,18 +45,20 @@ static void scan_translation_unit_trad (cpp_reader *);
|
||||
static void account_for_newlines (const unsigned char *, size_t);
|
||||
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
|
||||
|
||||
static void print_line (const struct line_map *, fileline, const char *);
|
||||
static void maybe_print_line (const struct line_map *, fileline);
|
||||
static void print_line (source_location, const char *);
|
||||
static void maybe_print_line (source_location);
|
||||
|
||||
/* Callback routines for the parser. Most of these are active only
|
||||
in specific modes. */
|
||||
static void cb_line_change (cpp_reader *, const cpp_token *, int);
|
||||
static void cb_define (cpp_reader *, fileline, cpp_hashnode *);
|
||||
static void cb_undef (cpp_reader *, fileline, cpp_hashnode *);
|
||||
static void cb_include (cpp_reader *, fileline, const unsigned char *,
|
||||
const char *, int);
|
||||
static void cb_ident (cpp_reader *, fileline, const cpp_string *);
|
||||
static void cb_def_pragma (cpp_reader *, fileline);
|
||||
static void cb_define (cpp_reader *, source_location, cpp_hashnode *);
|
||||
static void cb_undef (cpp_reader *, source_location, cpp_hashnode *);
|
||||
static void cb_include (cpp_reader *, source_location, const unsigned char *,
|
||||
const char *, int, const cpp_token **);
|
||||
static void cb_ident (cpp_reader *, source_location, const cpp_string *);
|
||||
static void cb_def_pragma (cpp_reader *, source_location);
|
||||
static void cb_read_pch (cpp_reader *pfile, const char *name,
|
||||
int fd, const char *orig_name);
|
||||
|
||||
/* Preprocess and output. */
|
||||
void
|
||||
@ -106,20 +108,26 @@ init_pp_output (FILE *out_stream)
|
||||
if (flag_dump_includes)
|
||||
cb->include = cb_include;
|
||||
|
||||
if (flag_pch_preprocess)
|
||||
{
|
||||
cb->valid_pch = c_common_valid_pch;
|
||||
cb->read_pch = cb_read_pch;
|
||||
}
|
||||
|
||||
if (flag_dump_macros == 'N' || flag_dump_macros == 'D')
|
||||
{
|
||||
cb->define = cb_define;
|
||||
cb->undef = cb_undef;
|
||||
}
|
||||
|
||||
/* Initialize the print structure. Setting print.line to -1 here is
|
||||
/* Initialize the print structure. Setting print.src_line to -1 here is
|
||||
a trick to guarantee that the first token of the file will cause
|
||||
a linemarker to be output by maybe_print_line. */
|
||||
print.line = (fileline) -1;
|
||||
print.src_line = -1;
|
||||
print.printed = 0;
|
||||
print.prev = 0;
|
||||
print.map = 0;
|
||||
print.outf = out_stream;
|
||||
print.first_time = 1;
|
||||
}
|
||||
|
||||
/* Writes out the preprocessed file, handling spacing and paste
|
||||
@ -171,13 +179,13 @@ scan_translation_unit (cpp_reader *pfile)
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust print.line for newlines embedded in output. */
|
||||
/* Adjust print.src_line for newlines embedded in output. */
|
||||
static void
|
||||
account_for_newlines (const unsigned char *str, size_t len)
|
||||
{
|
||||
while (len--)
|
||||
if (*str++ == '\n')
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
/* Writes out a traditionally preprocessed file. */
|
||||
@ -187,7 +195,7 @@ scan_translation_unit_trad (cpp_reader *pfile)
|
||||
while (_cpp_read_logical_line_trad (pfile))
|
||||
{
|
||||
size_t len = pfile->out.cur - pfile->out.base;
|
||||
maybe_print_line (print.map, pfile->out.first_line);
|
||||
maybe_print_line (pfile->out.first_line);
|
||||
fwrite (pfile->out.base, 1, len, print.outf);
|
||||
print.printed = 1;
|
||||
if (!CPP_OPTION (pfile, discard_comments))
|
||||
@ -199,52 +207,58 @@ scan_translation_unit_trad (cpp_reader *pfile)
|
||||
different line to the current one, output the required newlines or
|
||||
a line marker, and return 1. Otherwise return 0. */
|
||||
static void
|
||||
maybe_print_line (const struct line_map *map, fileline line)
|
||||
maybe_print_line (source_location src_loc)
|
||||
{
|
||||
const struct line_map *map = linemap_lookup (&line_table, src_loc);
|
||||
int src_line = SOURCE_LINE (map, src_loc);
|
||||
/* End the previous line of text. */
|
||||
if (print.printed)
|
||||
{
|
||||
putc ('\n', print.outf);
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
print.printed = 0;
|
||||
}
|
||||
|
||||
if (line >= print.line && line < print.line + 8)
|
||||
if (src_line >= print.src_line && src_line < print.src_line + 8)
|
||||
{
|
||||
while (line > print.line)
|
||||
while (src_line > print.src_line)
|
||||
{
|
||||
putc ('\n', print.outf);
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
}
|
||||
else
|
||||
print_line (map, line, "");
|
||||
print_line (src_loc, "");
|
||||
}
|
||||
|
||||
/* Output a line marker for logical line LINE. Special flags are "1"
|
||||
or "2" indicating entering or leaving a file. */
|
||||
static void
|
||||
print_line (const struct line_map *map, fileline line, const char *special_flags)
|
||||
print_line (source_location src_loc, const char *special_flags)
|
||||
{
|
||||
/* End any previous line of text. */
|
||||
if (print.printed)
|
||||
putc ('\n', print.outf);
|
||||
print.printed = 0;
|
||||
|
||||
print.line = line;
|
||||
if (!flag_no_line_commands)
|
||||
{
|
||||
const struct line_map *map = linemap_lookup (&line_table, src_loc);
|
||||
|
||||
size_t to_file_len = strlen (map->to_file);
|
||||
unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
|
||||
unsigned char *to_file_quoted =
|
||||
(unsigned char *) alloca (to_file_len * 4 + 1);
|
||||
unsigned char *p;
|
||||
|
||||
print.src_line = SOURCE_LINE (map, src_loc);
|
||||
|
||||
/* cpp_quote_string does not nul-terminate, so we have to do it
|
||||
ourselves. */
|
||||
p = cpp_quote_string (to_file_quoted,
|
||||
(unsigned char *)map->to_file, to_file_len);
|
||||
(unsigned char *) map->to_file, to_file_len);
|
||||
*p = '\0';
|
||||
fprintf (print.outf, "# %u \"%s\"%s",
|
||||
SOURCE_LINE (map, print.line),
|
||||
print.src_line == 0 ? 1 : print.src_line,
|
||||
to_file_quoted, special_flags);
|
||||
|
||||
if (map->sysp == 2)
|
||||
@ -262,10 +276,12 @@ static void
|
||||
cb_line_change (cpp_reader *pfile, const cpp_token *token,
|
||||
int parsing_args)
|
||||
{
|
||||
source_location src_loc = token->src_loc;
|
||||
|
||||
if (token->type == CPP_EOF || parsing_args)
|
||||
return;
|
||||
|
||||
maybe_print_line (print.map, token->line);
|
||||
maybe_print_line (src_loc);
|
||||
print.prev = 0;
|
||||
print.source = 0;
|
||||
|
||||
@ -276,30 +292,28 @@ cb_line_change (cpp_reader *pfile, const cpp_token *token,
|
||||
ought to care. Some things do care; the fault lies with them. */
|
||||
if (!CPP_OPTION (pfile, traditional))
|
||||
{
|
||||
const struct line_map *map = linemap_lookup (&line_table, src_loc);
|
||||
int spaces = SOURCE_COLUMN (map, src_loc) - 2;
|
||||
print.printed = 1;
|
||||
if (token->col > 2)
|
||||
{
|
||||
unsigned int spaces = token->col - 2;
|
||||
|
||||
while (spaces--)
|
||||
putc (' ', print.outf);
|
||||
}
|
||||
while (-- spaces >= 0)
|
||||
putc (' ', print.outf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
|
||||
cb_ident (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
|
||||
const cpp_string *str)
|
||||
{
|
||||
maybe_print_line (print.map, line);
|
||||
maybe_print_line (line);
|
||||
fprintf (print.outf, "#ident %s\n", str->text);
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node)
|
||||
cb_define (cpp_reader *pfile, source_location line, cpp_hashnode *node)
|
||||
{
|
||||
maybe_print_line (print.map, line);
|
||||
maybe_print_line (line);
|
||||
fputs ("#define ", print.outf);
|
||||
|
||||
/* 'D' is whole definition; 'N' is name only. */
|
||||
@ -310,49 +324,64 @@ cb_define (cpp_reader *pfile, fileline line, cpp_hashnode *node)
|
||||
fputs ((const char *) NODE_NAME (node), print.outf);
|
||||
|
||||
putc ('\n', print.outf);
|
||||
print.line++;
|
||||
if (linemap_lookup (&line_table, line)->to_line != 0)
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
|
||||
cb_undef (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
|
||||
cpp_hashnode *node)
|
||||
{
|
||||
maybe_print_line (print.map, line);
|
||||
maybe_print_line (line);
|
||||
fprintf (print.outf, "#undef %s\n", NODE_NAME (node));
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, fileline line,
|
||||
const unsigned char *dir, const char *header, int angle_brackets)
|
||||
cb_include (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
|
||||
const unsigned char *dir, const char *header, int angle_brackets,
|
||||
const cpp_token **comments)
|
||||
{
|
||||
maybe_print_line (print.map, line);
|
||||
maybe_print_line (line);
|
||||
if (angle_brackets)
|
||||
fprintf (print.outf, "#%s <%s>\n", dir, header);
|
||||
fprintf (print.outf, "#%s <%s>", dir, header);
|
||||
else
|
||||
fprintf (print.outf, "#%s \"%s\"\n", dir, header);
|
||||
print.line++;
|
||||
fprintf (print.outf, "#%s \"%s\"", dir, header);
|
||||
|
||||
if (comments != NULL)
|
||||
{
|
||||
while (*comments != NULL)
|
||||
{
|
||||
if ((*comments)->flags & PREV_WHITE)
|
||||
putc (' ', print.outf);
|
||||
cpp_output_token (*comments, print.outf);
|
||||
++comments;
|
||||
}
|
||||
}
|
||||
|
||||
putc ('\n', print.outf);
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
/* Callback called when -fworking-director and -E to emit working
|
||||
diretory in cpp output file. */
|
||||
directory in cpp output file. */
|
||||
|
||||
void
|
||||
pp_dir_change (cpp_reader *pfile ATTRIBUTE_UNUSED, const char *dir)
|
||||
{
|
||||
size_t to_file_len = strlen (dir);
|
||||
unsigned char *to_file_quoted = alloca (to_file_len * 4 + 1);
|
||||
unsigned char *to_file_quoted =
|
||||
(unsigned char *) alloca (to_file_len * 4 + 1);
|
||||
unsigned char *p;
|
||||
|
||||
/* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
|
||||
/* cpp_quote_string does not nul-terminate, so we have to do it ourselves. */
|
||||
p = cpp_quote_string (to_file_quoted, (unsigned char *) dir, to_file_len);
|
||||
*p = '\0';
|
||||
fprintf (print.outf, "# 1 \"%s//\"\n", to_file_quoted);
|
||||
}
|
||||
|
||||
/* The file name, line number or system header flags have changed, as
|
||||
described in MAP. From this point on, the old print.map might be
|
||||
pointing to freed memory, and so must not be dereferenced. */
|
||||
described in MAP. */
|
||||
|
||||
void
|
||||
pp_file_change (const struct line_map *map)
|
||||
@ -364,38 +393,38 @@ pp_file_change (const struct line_map *map)
|
||||
|
||||
if (map != NULL)
|
||||
{
|
||||
/* First time? */
|
||||
if (print.map == NULL)
|
||||
if (print.first_time)
|
||||
{
|
||||
/* Avoid printing foo.i when the main file is foo.c. */
|
||||
if (!cpp_get_options (parse_in)->preprocessed)
|
||||
print_line (map, map->from_line, flags);
|
||||
print_line (map->start_location, flags);
|
||||
print.first_time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Bring current file to correct line when entering a new file. */
|
||||
if (map->reason == LC_ENTER)
|
||||
maybe_print_line (map - 1, map->from_line - 1);
|
||||
|
||||
{
|
||||
const struct line_map *from = INCLUDED_FROM (&line_table, map);
|
||||
maybe_print_line (LAST_SOURCE_LINE_LOCATION (from));
|
||||
}
|
||||
if (map->reason == LC_ENTER)
|
||||
flags = " 1";
|
||||
else if (map->reason == LC_LEAVE)
|
||||
flags = " 2";
|
||||
print_line (map, map->from_line, flags);
|
||||
print_line (map->start_location, flags);
|
||||
}
|
||||
}
|
||||
|
||||
print.map = map;
|
||||
}
|
||||
|
||||
/* Copy a #pragma directive to the preprocessed output. */
|
||||
static void
|
||||
cb_def_pragma (cpp_reader *pfile, fileline line)
|
||||
cb_def_pragma (cpp_reader *pfile, source_location line)
|
||||
{
|
||||
maybe_print_line (print.map, line);
|
||||
maybe_print_line (line);
|
||||
fputs ("#pragma ", print.outf);
|
||||
cpp_output_line (pfile, print.outf);
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
/* Dump out the hash table. */
|
||||
@ -408,8 +437,22 @@ dump_macro (cpp_reader *pfile, cpp_hashnode *node, void *v ATTRIBUTE_UNUSED)
|
||||
fputs ((const char *) cpp_macro_definition (pfile, node),
|
||||
print.outf);
|
||||
putc ('\n', print.outf);
|
||||
print.line++;
|
||||
print.src_line++;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Load in the PCH file NAME, open on FD. It was originally searched for
|
||||
by ORIG_NAME. Also, print out a #include command so that the PCH
|
||||
file can be loaded when the preprocessed output is compiled. */
|
||||
|
||||
static void
|
||||
cb_read_pch (cpp_reader *pfile, const char *name,
|
||||
int fd, const char *orig_name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
c_common_read_pch (pfile, name, fd, orig_name);
|
||||
|
||||
fprintf (print.outf, "#pragma GCC pch_preprocess \"%s\"\n", name);
|
||||
print.src_line++;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
|
||||
Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -34,15 +34,20 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "c-common.h"
|
||||
#include "output.h"
|
||||
#include "tm_p.h"
|
||||
#include "vec.h"
|
||||
#include "target.h"
|
||||
#include "diagnostic.h"
|
||||
#include "opts.h"
|
||||
|
||||
#define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
|
||||
#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
|
||||
#define GCC_BAD(gmsgid) \
|
||||
do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
|
||||
#define GCC_BAD2(gmsgid, arg) \
|
||||
do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
|
||||
|
||||
typedef struct align_stack GTY(())
|
||||
{
|
||||
int alignment;
|
||||
unsigned int num_pushes;
|
||||
tree id;
|
||||
int alignment;
|
||||
tree id;
|
||||
struct align_stack * prev;
|
||||
} align_stack;
|
||||
|
||||
@ -53,13 +58,14 @@ static void handle_pragma_pack (cpp_reader *);
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
|
||||
/* If we have a "global" #pragma pack(<n>) in effect when the first
|
||||
#pragma pack(push,<n>) is encountered, this stores the value of
|
||||
maximum_field_alignment in effect. When the final pop_alignment()
|
||||
#pragma pack(push,<n>) is encountered, this stores the value of
|
||||
maximum_field_alignment in effect. When the final pop_alignment()
|
||||
happens, we restore the value to this, not to a value of 0 for
|
||||
maximum_field_alignment. Value is in bits. */
|
||||
static int default_alignment;
|
||||
#define SET_GLOBAL_ALIGNMENT(ALIGN) \
|
||||
(default_alignment = maximum_field_alignment = (ALIGN))
|
||||
#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
|
||||
? &default_alignment \
|
||||
: &alignment_stack->alignment) = (ALIGN))
|
||||
|
||||
static void push_alignment (int, tree);
|
||||
static void pop_alignment (tree);
|
||||
@ -68,31 +74,23 @@ static void pop_alignment (tree);
|
||||
static void
|
||||
push_alignment (int alignment, tree id)
|
||||
{
|
||||
if (alignment_stack == NULL
|
||||
|| alignment_stack->alignment != alignment
|
||||
|| id != NULL_TREE)
|
||||
{
|
||||
align_stack * entry;
|
||||
align_stack * entry;
|
||||
|
||||
entry = ggc_alloc (sizeof (* entry));
|
||||
entry = GGC_NEW (align_stack);
|
||||
|
||||
entry->alignment = alignment;
|
||||
entry->num_pushes = 1;
|
||||
entry->id = id;
|
||||
entry->prev = alignment_stack;
|
||||
|
||||
/* The current value of maximum_field_alignment is not necessarily
|
||||
0 since there may be a #pragma pack(<n>) in effect; remember it
|
||||
so that we can restore it after the final #pragma pop(). */
|
||||
if (alignment_stack == NULL)
|
||||
default_alignment = maximum_field_alignment;
|
||||
|
||||
alignment_stack = entry;
|
||||
entry->alignment = alignment;
|
||||
entry->id = id;
|
||||
entry->prev = alignment_stack;
|
||||
|
||||
maximum_field_alignment = alignment;
|
||||
}
|
||||
else
|
||||
alignment_stack->num_pushes ++;
|
||||
/* The current value of maximum_field_alignment is not necessarily
|
||||
0 since there may be a #pragma pack(<n>) in effect; remember it
|
||||
so that we can restore it after the final #pragma pop(). */
|
||||
if (alignment_stack == NULL)
|
||||
default_alignment = maximum_field_alignment;
|
||||
|
||||
alignment_stack = entry;
|
||||
|
||||
maximum_field_alignment = alignment;
|
||||
}
|
||||
|
||||
/* Undo a push of an alignment onto the stack. */
|
||||
@ -100,14 +98,9 @@ static void
|
||||
pop_alignment (tree id)
|
||||
{
|
||||
align_stack * entry;
|
||||
|
||||
|
||||
if (alignment_stack == NULL)
|
||||
{
|
||||
warning ("\
|
||||
#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
|
||||
);
|
||||
return;
|
||||
}
|
||||
GCC_BAD ("#pragma pack (pop) encountered without matching #pragma pack (push)");
|
||||
|
||||
/* If we got an identifier, strip away everything above the target
|
||||
entry so that the next step will restore the state just below it. */
|
||||
@ -116,73 +109,70 @@ pop_alignment (tree 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>)"
|
||||
warning (OPT_Wpragmas, "\
|
||||
#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s)"
|
||||
, IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
|
||||
}
|
||||
|
||||
if (-- alignment_stack->num_pushes == 0)
|
||||
{
|
||||
entry = alignment_stack->prev;
|
||||
entry = alignment_stack->prev;
|
||||
|
||||
if (entry == NULL)
|
||||
maximum_field_alignment = default_alignment;
|
||||
else
|
||||
maximum_field_alignment = entry->alignment;
|
||||
maximum_field_alignment = entry ? entry->alignment : default_alignment;
|
||||
|
||||
alignment_stack = entry;
|
||||
}
|
||||
alignment_stack = entry;
|
||||
}
|
||||
#else /* not HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
|
||||
#define push_alignment(ID, N) \
|
||||
GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target")
|
||||
GCC_BAD ("#pragma pack(push[, id], <n>) is not supported on this target")
|
||||
#define pop_alignment(ID) \
|
||||
GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target")
|
||||
GCC_BAD ("#pragma pack(pop[, id], <n>) is not supported on this target")
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
/* #pragma pack ()
|
||||
#pragma pack (N)
|
||||
|
||||
|
||||
#pragma pack (push)
|
||||
#pragma pack (push, N)
|
||||
#pragma pack (push, ID)
|
||||
#pragma pack (push, ID, N)
|
||||
#pragma pack (pop)
|
||||
#pragma pack (pop, ID) */
|
||||
static void
|
||||
handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
|
||||
{
|
||||
tree x, id = 0;
|
||||
int align = -1;
|
||||
enum cpp_ttype token;
|
||||
enum { set, push, pop } action;
|
||||
|
||||
if (c_lex (&x) != CPP_OPEN_PAREN)
|
||||
GCC_BAD ("missing '(' after '#pragma pack' - ignored");
|
||||
if (pragma_lex (&x) != CPP_OPEN_PAREN)
|
||||
GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
|
||||
|
||||
token = c_lex (&x);
|
||||
token = pragma_lex (&x);
|
||||
if (token == CPP_CLOSE_PAREN)
|
||||
{
|
||||
action = set;
|
||||
align = 0;
|
||||
align = initial_max_fld_align;
|
||||
}
|
||||
else if (token == CPP_NUMBER)
|
||||
{
|
||||
if (TREE_CODE (x) != INTEGER_CST)
|
||||
GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
|
||||
align = TREE_INT_CST_LOW (x);
|
||||
action = set;
|
||||
if (c_lex (&x) != CPP_CLOSE_PAREN)
|
||||
GCC_BAD ("malformed '#pragma pack' - ignored");
|
||||
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
|
||||
GCC_BAD ("malformed %<#pragma pack%> - ignored");
|
||||
}
|
||||
else if (token == CPP_NAME)
|
||||
{
|
||||
#define GCC_BAD_ACTION do { if (action == push) \
|
||||
GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
|
||||
#define GCC_BAD_ACTION do { if (action != pop) \
|
||||
GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
|
||||
else \
|
||||
GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
|
||||
GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
|
||||
} while (0)
|
||||
|
||||
const char *op = IDENTIFIER_POINTER (x);
|
||||
@ -191,33 +181,25 @@ handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
else if (!strcmp (op, "pop"))
|
||||
action = pop;
|
||||
else
|
||||
GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
|
||||
GCC_BAD2 ("unknown action %qs for %<#pragma pack%> - ignored", op);
|
||||
|
||||
token = c_lex (&x);
|
||||
if (token != CPP_COMMA && action == push)
|
||||
GCC_BAD_ACTION;
|
||||
|
||||
if (token == CPP_COMMA)
|
||||
while ((token = pragma_lex (&x)) == CPP_COMMA)
|
||||
{
|
||||
token = c_lex (&x);
|
||||
if (token == CPP_NAME)
|
||||
token = pragma_lex (&x);
|
||||
if (token == CPP_NAME && id == 0)
|
||||
{
|
||||
id = x;
|
||||
if (action == push && c_lex (&x) != CPP_COMMA)
|
||||
GCC_BAD_ACTION;
|
||||
token = c_lex (&x);
|
||||
}
|
||||
|
||||
if (action == push)
|
||||
else if (token == CPP_NUMBER && action == push && align == -1)
|
||||
{
|
||||
if (token == CPP_NUMBER)
|
||||
{
|
||||
align = TREE_INT_CST_LOW (x);
|
||||
token = c_lex (&x);
|
||||
}
|
||||
else
|
||||
GCC_BAD_ACTION;
|
||||
if (TREE_CODE (x) != INTEGER_CST)
|
||||
GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
|
||||
align = TREE_INT_CST_LOW (x);
|
||||
if (align == -1)
|
||||
action = set;
|
||||
}
|
||||
else
|
||||
GCC_BAD_ACTION;
|
||||
}
|
||||
|
||||
if (token != CPP_CLOSE_PAREN)
|
||||
@ -225,10 +207,13 @@ handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
#undef GCC_BAD_ACTION
|
||||
}
|
||||
else
|
||||
GCC_BAD ("malformed '#pragma pack' - ignored");
|
||||
GCC_BAD ("malformed %<#pragma pack%> - ignored");
|
||||
|
||||
if (c_lex (&x) != CPP_EOF)
|
||||
warning ("junk at end of '#pragma pack'");
|
||||
if (pragma_lex (&x) != CPP_EOF)
|
||||
warning (OPT_Wpragmas, "junk at end of %<#pragma pack%>");
|
||||
|
||||
if (flag_pack_struct)
|
||||
GCC_BAD ("#pragma pack has no effect with -fpack-struct - ignored");
|
||||
|
||||
if (action != pop)
|
||||
switch (align)
|
||||
@ -241,6 +226,12 @@ handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
case 16:
|
||||
align *= BITS_PER_UNIT;
|
||||
break;
|
||||
case -1:
|
||||
if (action == push)
|
||||
{
|
||||
align = maximum_field_alignment;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GCC_BAD2 ("alignment must be a small power of two, not %d", align);
|
||||
}
|
||||
@ -249,7 +240,7 @@ handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
{
|
||||
case set: SET_GLOBAL_ALIGNMENT (align); break;
|
||||
case push: push_alignment (align, id); break;
|
||||
case pop: pop_alignment (id); break;
|
||||
case pop: pop_alignment (id); break;
|
||||
}
|
||||
}
|
||||
#endif /* HANDLE_PRAGMA_PACK */
|
||||
@ -275,8 +266,8 @@ apply_pragma_weak (tree decl, tree value)
|
||||
if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
|
||||
&& !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */
|
||||
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|
||||
warning ("%Japplying #pragma weak '%D' after first use results "
|
||||
"in unspecified behavior", decl, decl);
|
||||
warning (OPT_Wpragmas, "applying #pragma weak %q+D after first use "
|
||||
"results in unspecified behavior", decl);
|
||||
|
||||
declare_weak (decl);
|
||||
}
|
||||
@ -297,7 +288,7 @@ maybe_apply_pragma_weak (tree decl)
|
||||
return;
|
||||
/* If it's not a function or a variable, it can't be weak.
|
||||
FIXME: what kinds of things are visible outside this file but
|
||||
aren't functions or variables? Should this be an abort() instead? */
|
||||
aren't functions or variables? Should this be an assert instead? */
|
||||
if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
|
||||
return;
|
||||
|
||||
@ -312,29 +303,56 @@ maybe_apply_pragma_weak (tree decl)
|
||||
}
|
||||
}
|
||||
|
||||
/* Process all "#pragma weak A = B" directives where we have not seen
|
||||
a decl for A. */
|
||||
void
|
||||
maybe_apply_pending_pragma_weaks (void)
|
||||
{
|
||||
tree *p, t, alias_id, id, decl, *next;
|
||||
|
||||
for (p = &pending_weaks; (t = *p) ; p = next)
|
||||
{
|
||||
next = &TREE_CHAIN (t);
|
||||
alias_id = TREE_PURPOSE (t);
|
||||
id = TREE_VALUE (t);
|
||||
|
||||
if (TREE_VALUE (t) == NULL)
|
||||
continue;
|
||||
|
||||
decl = build_decl (FUNCTION_DECL, alias_id, default_function_type);
|
||||
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
TREE_PUBLIC (decl) = 1;
|
||||
DECL_EXTERNAL (decl) = 1;
|
||||
DECL_WEAK (decl) = 1;
|
||||
|
||||
assemble_alias (decl, id);
|
||||
}
|
||||
}
|
||||
|
||||
/* #pragma weak name [= value] */
|
||||
static void
|
||||
handle_pragma_weak (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
|
||||
{
|
||||
tree name, value, x, decl;
|
||||
enum cpp_ttype t;
|
||||
|
||||
value = 0;
|
||||
|
||||
if (c_lex (&name) != CPP_NAME)
|
||||
if (pragma_lex (&name) != CPP_NAME)
|
||||
GCC_BAD ("malformed #pragma weak, ignored");
|
||||
t = c_lex (&x);
|
||||
t = pragma_lex (&x);
|
||||
if (t == CPP_EQ)
|
||||
{
|
||||
if (c_lex (&value) != CPP_NAME)
|
||||
if (pragma_lex (&value) != CPP_NAME)
|
||||
GCC_BAD ("malformed #pragma weak, ignored");
|
||||
t = c_lex (&x);
|
||||
t = pragma_lex (&x);
|
||||
}
|
||||
if (t != CPP_EOF)
|
||||
warning ("junk at end of #pragma weak");
|
||||
warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
|
||||
|
||||
decl = identifier_global_value (name);
|
||||
if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
|
||||
if (decl && DECL_P (decl))
|
||||
{
|
||||
apply_pragma_weak (decl, value);
|
||||
if (value)
|
||||
@ -345,83 +363,142 @@ handle_pragma_weak (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
}
|
||||
#else
|
||||
void
|
||||
maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED)
|
||||
maybe_apply_pragma_weak (tree ARG_UNUSED (decl))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
maybe_apply_pending_pragma_weaks (void)
|
||||
{
|
||||
}
|
||||
#endif /* HANDLE_PRAGMA_WEAK */
|
||||
|
||||
/* GCC supports two #pragma directives for renaming the external
|
||||
symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
|
||||
compatibility with the Solaris and Tru64 system headers. GCC also
|
||||
has its own notation for this, __asm__("name") annotations.
|
||||
|
||||
Corner cases of these features and their interaction:
|
||||
|
||||
1) Both pragmas silently apply only to declarations with external
|
||||
linkage (that is, TREE_PUBLIC || DECL_EXTERNAL). Asm labels
|
||||
do not have this restriction.
|
||||
|
||||
2) In C++, both #pragmas silently apply only to extern "C" declarations.
|
||||
Asm labels do not have this restriction.
|
||||
|
||||
3) If any of the three ways of changing DECL_ASSEMBLER_NAME is
|
||||
applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the
|
||||
new name is different, a warning issues and the name does not change.
|
||||
|
||||
4) The "source name" for #pragma redefine_extname is the DECL_NAME,
|
||||
*not* the DECL_ASSEMBLER_NAME.
|
||||
|
||||
5) If #pragma extern_prefix is in effect and a declaration occurs
|
||||
with an __asm__ name, the #pragma extern_prefix is silently
|
||||
ignored for that declaration.
|
||||
|
||||
6) If #pragma extern_prefix and #pragma redefine_extname apply to
|
||||
the same declaration, whichever triggered first wins, and a warning
|
||||
is issued. (We would like to have #pragma redefine_extname always
|
||||
win, but it can appear either before or after the declaration, and
|
||||
if it appears afterward, we have no way of knowing whether a modified
|
||||
DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.) */
|
||||
|
||||
static GTY(()) tree pending_redefine_extname;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
|
||||
static void handle_pragma_redefine_extname (cpp_reader *);
|
||||
|
||||
/* #pragma redefined_extname oldname newname */
|
||||
/* #pragma redefine_extname oldname newname */
|
||||
static void
|
||||
handle_pragma_redefine_extname (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
|
||||
{
|
||||
tree oldname, newname, decl, x;
|
||||
enum cpp_ttype t;
|
||||
|
||||
if (c_lex (&oldname) != CPP_NAME)
|
||||
{
|
||||
warning ("malformed #pragma redefine_extname, ignored");
|
||||
return;
|
||||
}
|
||||
if (c_lex (&newname) != CPP_NAME)
|
||||
{
|
||||
warning ("malformed #pragma redefine_extname, ignored");
|
||||
return;
|
||||
}
|
||||
t = c_lex (&x);
|
||||
if (pragma_lex (&oldname) != CPP_NAME)
|
||||
GCC_BAD ("malformed #pragma redefine_extname, ignored");
|
||||
if (pragma_lex (&newname) != CPP_NAME)
|
||||
GCC_BAD ("malformed #pragma redefine_extname, ignored");
|
||||
t = pragma_lex (&x);
|
||||
if (t != CPP_EOF)
|
||||
warning ("junk at end of #pragma redefine_extname");
|
||||
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
|
||||
|
||||
if (!flag_mudflap && !targetm.handle_pragma_redefine_extname)
|
||||
{
|
||||
if (warn_unknown_pragmas > in_system_header)
|
||||
warning (OPT_Wunknown_pragmas,
|
||||
"#pragma redefine_extname not supported on this target");
|
||||
return;
|
||||
}
|
||||
|
||||
decl = identifier_global_value (oldname);
|
||||
if (decl && (TREE_CODE (decl) == FUNCTION_DECL
|
||||
|| TREE_CODE (decl) == VAR_DECL))
|
||||
if (decl
|
||||
&& (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
|
||||
&& (TREE_CODE (decl) == FUNCTION_DECL
|
||||
|| TREE_CODE (decl) == VAR_DECL)
|
||||
&& has_c_linkage (decl))
|
||||
{
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (decl)
|
||||
&& DECL_ASSEMBLER_NAME (decl) != newname)
|
||||
warning ("#pragma redefine_extname conflicts with declaration");
|
||||
change_decl_assembler_name (decl, newname);
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (decl))
|
||||
{
|
||||
const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
name = targetm.strip_name_encoding (name);
|
||||
|
||||
if (strcmp (name, IDENTIFIER_POINTER (newname)))
|
||||
warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
|
||||
"conflict with previous rename");
|
||||
}
|
||||
else
|
||||
change_decl_assembler_name (decl, newname);
|
||||
}
|
||||
else
|
||||
add_to_renaming_pragma_list(oldname, newname);
|
||||
/* We have to add this to the rename list even if there's already
|
||||
a global value that doesn't meet the above criteria, because in
|
||||
C++ "struct foo {...};" puts "foo" in the current namespace but
|
||||
does *not* conflict with a subsequent declaration of a function
|
||||
or variable foo. See g++.dg/other/pragma-re-2.C. */
|
||||
add_to_renaming_pragma_list (oldname, newname);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This is called from here and from ia64.c. */
|
||||
void
|
||||
add_to_renaming_pragma_list (tree oldname, tree newname)
|
||||
{
|
||||
tree previous = purpose_member (oldname, pending_redefine_extname);
|
||||
if (previous)
|
||||
{
|
||||
if (TREE_VALUE (previous) != newname)
|
||||
warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
|
||||
"conflict with previous #pragma redefine_extname");
|
||||
return;
|
||||
}
|
||||
|
||||
pending_redefine_extname
|
||||
= tree_cons (oldname, newname, pending_redefine_extname);
|
||||
}
|
||||
|
||||
static GTY(()) tree pragma_extern_prefix;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
|
||||
static void handle_pragma_extern_prefix (cpp_reader *);
|
||||
|
||||
/* #pragma extern_prefix "prefix" */
|
||||
static void
|
||||
handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
|
||||
{
|
||||
tree prefix, x;
|
||||
enum cpp_ttype t;
|
||||
|
||||
if (c_lex (&prefix) != CPP_STRING)
|
||||
{
|
||||
warning ("malformed #pragma extern_prefix, ignored");
|
||||
return;
|
||||
}
|
||||
t = c_lex (&x);
|
||||
if (pragma_lex (&prefix) != CPP_STRING)
|
||||
GCC_BAD ("malformed #pragma extern_prefix, ignored");
|
||||
t = pragma_lex (&x);
|
||||
if (t != CPP_EOF)
|
||||
warning ("junk at end of #pragma extern_prefix");
|
||||
warning (OPT_Wpragmas, "junk at end of %<#pragma extern_prefix%>");
|
||||
|
||||
/* Note that the length includes the null terminator. */
|
||||
pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
|
||||
if (targetm.handle_pragma_extern_prefix)
|
||||
/* Note that the length includes the null terminator. */
|
||||
pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
|
||||
else if (warn_unknown_pragmas > in_system_header)
|
||||
warning (OPT_Wunknown_pragmas,
|
||||
"#pragma extern_prefix not supported on this target");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hook from the front ends to apply the results of one of the preceding
|
||||
pragmas that rename variables. */
|
||||
@ -429,83 +506,330 @@ handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
tree
|
||||
maybe_apply_renaming_pragma (tree decl, tree asmname)
|
||||
{
|
||||
tree oldname;
|
||||
tree *p, t;
|
||||
|
||||
/* Copied from the check in set_decl_assembler_name. */
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL
|
||||
|| (TREE_CODE (decl) == VAR_DECL
|
||||
&& (TREE_STATIC (decl)
|
||||
|| DECL_EXTERNAL (decl)
|
||||
|| TREE_PUBLIC (decl))))
|
||||
oldname = DECL_ASSEMBLER_NAME (decl);
|
||||
else
|
||||
/* The renaming pragmas are only applied to declarations with
|
||||
external linkage. */
|
||||
if ((TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
|
||||
|| (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
|
||||
|| !has_c_linkage (decl))
|
||||
return asmname;
|
||||
|
||||
/* If the name begins with a *, that's a sign of an asmname attached to
|
||||
a previous declaration. */
|
||||
if (IDENTIFIER_POINTER (oldname)[0] == '*')
|
||||
/* If the DECL_ASSEMBLER_NAME is already set, it does not change,
|
||||
but we may warn about a rename that conflicts. */
|
||||
if (DECL_ASSEMBLER_NAME_SET_P (decl))
|
||||
{
|
||||
const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1;
|
||||
if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0)
|
||||
warning ("asm declaration conflicts with previous rename");
|
||||
asmname = build_string (strlen (oldasmname), oldasmname);
|
||||
const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
|
||||
oldname = targetm.strip_name_encoding (oldname);
|
||||
|
||||
if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
|
||||
warning (OPT_Wpragmas, "asm declaration ignored due to "
|
||||
"conflict with previous rename");
|
||||
|
||||
/* Take any pending redefine_extname off the list. */
|
||||
for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t))
|
||||
if (DECL_NAME (decl) == TREE_PURPOSE (t))
|
||||
{
|
||||
/* Only warn if there is a conflict. */
|
||||
if (strcmp (IDENTIFIER_POINTER (TREE_VALUE (t)), oldname))
|
||||
warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
|
||||
"conflict with previous rename");
|
||||
|
||||
*p = TREE_CHAIN (t);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
tree *p, t;
|
||||
/* Find out if we have a pending #pragma redefine_extname. */
|
||||
for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t))
|
||||
if (DECL_NAME (decl) == TREE_PURPOSE (t))
|
||||
{
|
||||
tree newname = TREE_VALUE (t);
|
||||
*p = TREE_CHAIN (t);
|
||||
|
||||
for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t))
|
||||
if (oldname == TREE_PURPOSE (t))
|
||||
{
|
||||
const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t));
|
||||
/* If we already have an asmname, #pragma redefine_extname is
|
||||
ignored (with a warning if it conflicts). */
|
||||
if (asmname)
|
||||
{
|
||||
if (strcmp (TREE_STRING_POINTER (asmname),
|
||||
IDENTIFIER_POINTER (newname)) != 0)
|
||||
warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
|
||||
"conflict with __asm__ declaration");
|
||||
return asmname;
|
||||
}
|
||||
|
||||
if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0)
|
||||
warning ("#pragma redefine_extname conflicts with declaration");
|
||||
*p = TREE_CHAIN (t);
|
||||
/* Otherwise we use what we've got; #pragma extern_prefix is
|
||||
silently ignored. */
|
||||
return build_string (IDENTIFIER_LENGTH (newname),
|
||||
IDENTIFIER_POINTER (newname));
|
||||
}
|
||||
|
||||
return build_string (strlen (newname), newname);
|
||||
}
|
||||
}
|
||||
/* If we've got an asmname, #pragma extern_prefix is silently ignored. */
|
||||
if (asmname)
|
||||
return asmname;
|
||||
|
||||
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
|
||||
if (pragma_extern_prefix && !asmname)
|
||||
/* If #pragma extern_prefix is in effect, apply it. */
|
||||
if (pragma_extern_prefix)
|
||||
{
|
||||
char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix),
|
||||
IDENTIFIER_POINTER (oldname), NULL);
|
||||
asmname = build_string (strlen (x), x);
|
||||
free (x);
|
||||
return asmname;
|
||||
}
|
||||
#endif
|
||||
const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix);
|
||||
size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1;
|
||||
|
||||
return asmname;
|
||||
const char *id = IDENTIFIER_POINTER (DECL_NAME (decl));
|
||||
size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl));
|
||||
|
||||
char *newname = (char *) alloca (plen + ilen + 1);
|
||||
|
||||
memcpy (newname, prefix, plen);
|
||||
memcpy (newname + plen, id, ilen + 1);
|
||||
|
||||
return build_string (plen + ilen, newname);
|
||||
}
|
||||
|
||||
/* Nada. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Front-end wrapper for pragma registration to avoid dragging
|
||||
cpplib.h in almost everywhere. */
|
||||
|
||||
#ifdef HANDLE_PRAGMA_VISIBILITY
|
||||
static void handle_pragma_visibility (cpp_reader *);
|
||||
|
||||
typedef enum symbol_visibility visibility;
|
||||
DEF_VEC_I (visibility);
|
||||
DEF_VEC_ALLOC_I (visibility, heap);
|
||||
static VEC (visibility, heap) *visstack;
|
||||
|
||||
/* Push the visibility indicated by STR onto the top of the #pragma
|
||||
visibility stack. */
|
||||
|
||||
void
|
||||
c_register_pragma (const char *space, const char *name,
|
||||
void (*handler) (struct cpp_reader *))
|
||||
push_visibility (const char *str)
|
||||
{
|
||||
cpp_register_pragma (parse_in, space, name, handler);
|
||||
VEC_safe_push (visibility, heap, visstack,
|
||||
default_visibility);
|
||||
if (!strcmp (str, "default"))
|
||||
default_visibility = VISIBILITY_DEFAULT;
|
||||
else if (!strcmp (str, "internal"))
|
||||
default_visibility = VISIBILITY_INTERNAL;
|
||||
else if (!strcmp (str, "hidden"))
|
||||
default_visibility = VISIBILITY_HIDDEN;
|
||||
else if (!strcmp (str, "protected"))
|
||||
default_visibility = VISIBILITY_PROTECTED;
|
||||
else
|
||||
GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected");
|
||||
visibility_options.inpragma = 1;
|
||||
}
|
||||
|
||||
/* Pop a level of the #pragma visibility stack. */
|
||||
|
||||
void
|
||||
pop_visibility (void)
|
||||
{
|
||||
default_visibility = VEC_pop (visibility, visstack);
|
||||
visibility_options.inpragma
|
||||
= VEC_length (visibility, visstack) != 0;
|
||||
}
|
||||
|
||||
/* Sets the default visibility for symbols to something other than that
|
||||
specified on the command line. */
|
||||
|
||||
static void
|
||||
handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/* Form is #pragma GCC visibility push(hidden)|pop */
|
||||
tree x;
|
||||
enum cpp_ttype token;
|
||||
enum { bad, push, pop } action = bad;
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (token == CPP_NAME)
|
||||
{
|
||||
const char *op = IDENTIFIER_POINTER (x);
|
||||
if (!strcmp (op, "push"))
|
||||
action = push;
|
||||
else if (!strcmp (op, "pop"))
|
||||
action = pop;
|
||||
}
|
||||
if (bad == action)
|
||||
GCC_BAD ("#pragma GCC visibility must be followed by push or pop");
|
||||
else
|
||||
{
|
||||
if (pop == action)
|
||||
{
|
||||
if (!VEC_length (visibility, visstack))
|
||||
GCC_BAD ("no matching push for %<#pragma GCC visibility pop%>");
|
||||
else
|
||||
pop_visibility ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pragma_lex (&x) != CPP_OPEN_PAREN)
|
||||
GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
|
||||
token = pragma_lex (&x);
|
||||
if (token != CPP_NAME)
|
||||
GCC_BAD ("malformed #pragma GCC visibility push");
|
||||
else
|
||||
push_visibility (IDENTIFIER_POINTER (x));
|
||||
if (pragma_lex (&x) != CPP_CLOSE_PAREN)
|
||||
GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
|
||||
}
|
||||
}
|
||||
if (pragma_lex (&x) != CPP_EOF)
|
||||
warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
|
||||
{
|
||||
const char *kind_string, *option_string;
|
||||
unsigned int option_index;
|
||||
enum cpp_ttype token;
|
||||
diagnostic_t kind;
|
||||
tree x;
|
||||
|
||||
if (cfun)
|
||||
{
|
||||
error ("#pragma GCC diagnostic not allowed inside functions");
|
||||
return;
|
||||
}
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (token != CPP_NAME)
|
||||
GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>");
|
||||
kind_string = IDENTIFIER_POINTER (x);
|
||||
if (strcmp (kind_string, "error") == 0)
|
||||
kind = DK_ERROR;
|
||||
else if (strcmp (kind_string, "warning") == 0)
|
||||
kind = DK_WARNING;
|
||||
else if (strcmp (kind_string, "ignored") == 0)
|
||||
kind = DK_IGNORED;
|
||||
else
|
||||
GCC_BAD ("expected [error|warning|ignored] after %<#pragma GCC diagnostic%>");
|
||||
|
||||
token = pragma_lex (&x);
|
||||
if (token != CPP_STRING)
|
||||
GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
|
||||
option_string = TREE_STRING_POINTER (x);
|
||||
for (option_index = 0; option_index < cl_options_count; option_index++)
|
||||
if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
|
||||
{
|
||||
/* This overrides -Werror, for example. */
|
||||
diagnostic_classify_diagnostic (global_dc, option_index, kind);
|
||||
/* This makes sure the option is enabled, like -Wfoo would do. */
|
||||
if (cl_options[option_index].var_type == CLVC_BOOLEAN
|
||||
&& cl_options[option_index].flag_var
|
||||
&& kind != DK_IGNORED)
|
||||
*(int *) cl_options[option_index].flag_var = 1;
|
||||
return;
|
||||
}
|
||||
GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
|
||||
}
|
||||
|
||||
/* A vector of registered pragma callbacks. */
|
||||
|
||||
DEF_VEC_O (pragma_handler);
|
||||
DEF_VEC_ALLOC_O (pragma_handler, heap);
|
||||
|
||||
static VEC(pragma_handler, heap) *registered_pragmas;
|
||||
|
||||
/* Front-end wrappers for pragma registration to avoid dragging
|
||||
cpplib.h in almost everywhere. */
|
||||
|
||||
static void
|
||||
c_register_pragma_1 (const char *space, const char *name,
|
||||
pragma_handler handler, bool allow_expansion)
|
||||
{
|
||||
unsigned id;
|
||||
|
||||
VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
|
||||
id = VEC_length (pragma_handler, registered_pragmas);
|
||||
id += PRAGMA_FIRST_EXTERNAL - 1;
|
||||
|
||||
/* The C++ front end allocates 6 bits in cp_token; the C front end
|
||||
allocates 7 bits in c_token. At present this is sufficient. */
|
||||
gcc_assert (id < 64);
|
||||
|
||||
cpp_register_deferred_pragma (parse_in, space, name, id,
|
||||
allow_expansion, false);
|
||||
}
|
||||
|
||||
void
|
||||
c_register_pragma (const char *space, const char *name, pragma_handler handler)
|
||||
{
|
||||
c_register_pragma_1 (space, name, handler, false);
|
||||
}
|
||||
|
||||
void
|
||||
c_register_pragma_with_expansion (const char *space, const char *name,
|
||||
pragma_handler handler)
|
||||
{
|
||||
c_register_pragma_1 (space, name, handler, true);
|
||||
}
|
||||
|
||||
void
|
||||
c_invoke_pragma_handler (unsigned int id)
|
||||
{
|
||||
pragma_handler handler;
|
||||
|
||||
id -= PRAGMA_FIRST_EXTERNAL;
|
||||
handler = *VEC_index (pragma_handler, registered_pragmas, id);
|
||||
|
||||
handler (parse_in);
|
||||
}
|
||||
|
||||
/* Set up front-end pragmas. */
|
||||
void
|
||||
init_pragma (void)
|
||||
{
|
||||
if (flag_openmp && !flag_preprocess_only)
|
||||
{
|
||||
struct omp_pragma_def { const char *name; unsigned int id; };
|
||||
static const struct omp_pragma_def omp_pragmas[] = {
|
||||
{ "atomic", PRAGMA_OMP_ATOMIC },
|
||||
{ "barrier", PRAGMA_OMP_BARRIER },
|
||||
{ "critical", PRAGMA_OMP_CRITICAL },
|
||||
{ "flush", PRAGMA_OMP_FLUSH },
|
||||
{ "for", PRAGMA_OMP_FOR },
|
||||
{ "master", PRAGMA_OMP_MASTER },
|
||||
{ "ordered", PRAGMA_OMP_ORDERED },
|
||||
{ "parallel", PRAGMA_OMP_PARALLEL },
|
||||
{ "section", PRAGMA_OMP_SECTION },
|
||||
{ "sections", PRAGMA_OMP_SECTIONS },
|
||||
{ "single", PRAGMA_OMP_SINGLE },
|
||||
{ "threadprivate", PRAGMA_OMP_THREADPRIVATE }
|
||||
};
|
||||
|
||||
const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_omp_pragmas; ++i)
|
||||
cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
|
||||
omp_pragmas[i].id, true, true);
|
||||
}
|
||||
|
||||
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
|
||||
PRAGMA_GCC_PCH_PREPROCESS, false, false);
|
||||
|
||||
#ifdef HANDLE_PRAGMA_PACK
|
||||
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
|
||||
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
|
||||
#else
|
||||
c_register_pragma (0, "pack", handle_pragma_pack);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_WEAK
|
||||
c_register_pragma (0, "weak", handle_pragma_weak);
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
|
||||
c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname);
|
||||
#ifdef HANDLE_PRAGMA_VISIBILITY
|
||||
c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
|
||||
#endif
|
||||
#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
|
||||
|
||||
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
|
||||
|
||||
c_register_pragma_with_expansion (0, "redefine_extname", handle_pragma_redefine_extname);
|
||||
c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
|
||||
#endif
|
||||
|
||||
#ifdef REGISTER_TARGET_PRAGMAS
|
||||
REGISTER_TARGET_PRAGMAS ();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Pragma related interfaces.
|
||||
Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,12 +16,39 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_C_PRAGMA_H
|
||||
#define GCC_C_PRAGMA_H
|
||||
|
||||
#include <cpplib.h> /* For enum cpp_ttype. */
|
||||
|
||||
/* Pragma identifiers built in to the front end parsers. Identifiers
|
||||
for ancillary handlers will follow these. */
|
||||
typedef enum pragma_kind {
|
||||
PRAGMA_NONE = 0,
|
||||
|
||||
PRAGMA_OMP_ATOMIC,
|
||||
PRAGMA_OMP_BARRIER,
|
||||
PRAGMA_OMP_CRITICAL,
|
||||
PRAGMA_OMP_FLUSH,
|
||||
PRAGMA_OMP_FOR,
|
||||
PRAGMA_OMP_MASTER,
|
||||
PRAGMA_OMP_ORDERED,
|
||||
PRAGMA_OMP_PARALLEL,
|
||||
PRAGMA_OMP_PARALLEL_FOR,
|
||||
PRAGMA_OMP_PARALLEL_SECTIONS,
|
||||
PRAGMA_OMP_SECTION,
|
||||
PRAGMA_OMP_SECTIONS,
|
||||
PRAGMA_OMP_SINGLE,
|
||||
PRAGMA_OMP_THREADPRIVATE,
|
||||
|
||||
PRAGMA_GCC_PCH_PREPROCESS,
|
||||
|
||||
PRAGMA_FIRST_EXTERNAL
|
||||
} pragma_kind;
|
||||
|
||||
/* Cause the `yydebug' variable to be defined. */
|
||||
#define YYDEBUG 1
|
||||
extern int yydebug;
|
||||
@ -44,17 +71,42 @@ extern struct cpp_reader* parse_in;
|
||||
#define HANDLE_PRAGMA_PACK 1
|
||||
#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
|
||||
|
||||
/* It's safe to always leave visibility pragma enabled as if
|
||||
visibility is not supported on the host OS platform the
|
||||
statements are ignored. */
|
||||
#define HANDLE_PRAGMA_VISIBILITY 1
|
||||
extern void push_visibility (const char *);
|
||||
extern void pop_visibility (void);
|
||||
|
||||
extern void init_pragma (void);
|
||||
|
||||
/* Front-end wrapper for pragma registration to avoid dragging
|
||||
cpplib.h in almost everywhere. */
|
||||
extern void c_register_pragma (const char *, const char *,
|
||||
void (*) (struct cpp_reader *));
|
||||
/* Front-end wrappers for pragma registration. */
|
||||
typedef void (*pragma_handler)(struct cpp_reader *);
|
||||
extern void c_register_pragma (const char *, const char *, pragma_handler);
|
||||
extern void c_register_pragma_with_expansion (const char *, const char *,
|
||||
pragma_handler);
|
||||
extern void c_invoke_pragma_handler (unsigned int);
|
||||
|
||||
extern void maybe_apply_pragma_weak (tree);
|
||||
extern void maybe_apply_pending_pragma_weaks (void);
|
||||
extern tree maybe_apply_renaming_pragma (tree, tree);
|
||||
extern void add_to_renaming_pragma_list (tree, tree);
|
||||
|
||||
extern int c_lex (tree *);
|
||||
extern int c_lex_with_flags (tree *, unsigned char *);
|
||||
extern enum cpp_ttype pragma_lex (tree *);
|
||||
|
||||
/* This is not actually available to pragma parsers. It's merely a
|
||||
convenient location to declare this function for c-lex, after
|
||||
having enum cpp_ttype declared. */
|
||||
extern enum cpp_ttype c_lex_with_flags (tree *, location_t *, unsigned char *);
|
||||
|
||||
/* If 1, then lex strings into the execution character set.
|
||||
If 0, lex strings into the host character set.
|
||||
If -1, lex both, and chain them together, such that the former
|
||||
is the TREE_CHAIN of the latter. */
|
||||
extern int c_lex_string_translate;
|
||||
|
||||
/* If true, strings should be passed to the caller of c_lex completely
|
||||
unmolested (no concatenation, no translation). */
|
||||
extern bool c_lex_return_raw_strings;
|
||||
|
||||
#endif /* GCC_C_PRAGMA_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Various declarations for the C and C++ pretty-printers.
|
||||
Copyright (C) 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_C_PRETTY_PRINTER
|
||||
#define GCC_C_PRETTY_PRINTER
|
||||
@ -30,7 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
typedef enum
|
||||
{
|
||||
pp_c_flag_abstract = 1 << 1,
|
||||
pp_c_flag_last_bit = 2
|
||||
pp_c_flag_last_bit = 2
|
||||
} pp_c_pretty_print_flags;
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ struct c_pretty_print_info
|
||||
int *offset_list;
|
||||
|
||||
pp_flags flags;
|
||||
|
||||
|
||||
/* These must be overridden by each of the C and C++ front-end to
|
||||
reflect their understanding of syntactic productions when they differ. */
|
||||
c_pretty_print_fn declaration;
|
||||
@ -80,6 +80,7 @@ struct c_pretty_print_info
|
||||
|
||||
c_pretty_print_fn statement;
|
||||
|
||||
c_pretty_print_fn constant;
|
||||
c_pretty_print_fn id_expression;
|
||||
c_pretty_print_fn primary_expression;
|
||||
c_pretty_print_fn postfix_expression;
|
||||
@ -95,7 +96,7 @@ struct c_pretty_print_info
|
||||
#undef pp_base
|
||||
#define pp_base(PP) (&pp_c_base (PP)->base)
|
||||
|
||||
|
||||
|
||||
#define pp_c_tree_identifier(PPI, ID) \
|
||||
pp_c_identifier (PPI, IDENTIFIER_POINTER (ID))
|
||||
|
||||
@ -129,6 +130,8 @@ struct c_pretty_print_info
|
||||
#define pp_statement(PPI, S) \
|
||||
pp_c_base (PPI)->statement (pp_c_base (PPI), S)
|
||||
|
||||
#define pp_constant(PP, E) \
|
||||
pp_c_base (PP)->constant (pp_c_base (PP), E)
|
||||
#define pp_id_expression(PP, E) \
|
||||
pp_c_base (PP)->id_expression (pp_c_base (PP), E)
|
||||
#define pp_primary_expression(PPI, E) \
|
||||
@ -159,13 +162,19 @@ void pp_c_left_paren (c_pretty_printer *);
|
||||
void pp_c_right_paren (c_pretty_printer *);
|
||||
void pp_c_left_brace (c_pretty_printer *);
|
||||
void pp_c_right_brace (c_pretty_printer *);
|
||||
void pp_c_left_bracket (c_pretty_printer *);
|
||||
void pp_c_right_bracket (c_pretty_printer *);
|
||||
void pp_c_dot (c_pretty_printer *);
|
||||
void pp_c_ampersand (c_pretty_printer *);
|
||||
void pp_c_star (c_pretty_printer *);
|
||||
void pp_c_arrow (c_pretty_printer *);
|
||||
void pp_c_semicolon (c_pretty_printer *);
|
||||
void pp_c_complement (c_pretty_printer *);
|
||||
void pp_c_exclamation (c_pretty_printer *);
|
||||
void pp_c_space_for_pointer_operator (c_pretty_printer *, tree);
|
||||
|
||||
/* Declarations. */
|
||||
void pp_c_tree_decl_identifier (c_pretty_printer *, tree);
|
||||
void pp_c_function_definition (c_pretty_printer *, tree);
|
||||
void pp_c_attributes (c_pretty_printer *, tree);
|
||||
void pp_c_type_qualifier_list (c_pretty_printer *, tree);
|
||||
@ -186,6 +195,7 @@ void pp_c_statement (c_pretty_printer *, tree);
|
||||
void pp_c_expression (c_pretty_printer *, tree);
|
||||
void pp_c_logical_or_expression (c_pretty_printer *, tree);
|
||||
void pp_c_expression_list (c_pretty_printer *, tree);
|
||||
void pp_c_constructor_elts (c_pretty_printer *, VEC(constructor_elt,gc) *);
|
||||
void pp_c_call_argument_list (c_pretty_printer *, tree);
|
||||
void pp_c_unary_expression (c_pretty_printer *, tree);
|
||||
void pp_c_cast_expression (c_pretty_printer *, tree);
|
||||
@ -197,4 +207,6 @@ void pp_c_id_expression (c_pretty_printer *, tree);
|
||||
void pp_c_identifier (c_pretty_printer *, const char *);
|
||||
void pp_c_string_literal (c_pretty_printer *, tree);
|
||||
|
||||
void print_c_tree (FILE *file, tree t);
|
||||
|
||||
#endif /* GCC_C_PRETTY_PRINTER */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/* Save and restore call-clobbered registers which are live across a call.
|
||||
Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,17 +16,17 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "rtl.h"
|
||||
#include "regs.h"
|
||||
#include "insn-config.h"
|
||||
#include "flags.h"
|
||||
#include "regs.h"
|
||||
#include "hard-reg-set.h"
|
||||
#include "recog.h"
|
||||
#include "basic-block.h"
|
||||
@ -35,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "expr.h"
|
||||
#include "toplev.h"
|
||||
#include "tm_p.h"
|
||||
#include "addresses.h"
|
||||
|
||||
#ifndef MAX_MOVE_MAX
|
||||
#define MAX_MOVE_MAX MOVE_MAX
|
||||
@ -83,10 +84,6 @@ static int n_regs_saved;
|
||||
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 (rtx, rtx, void *);
|
||||
static void mark_referenced_regs (rtx);
|
||||
@ -157,11 +154,10 @@ init_caller_save (void)
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (TEST_HARD_REG_BIT
|
||||
(reg_class_contents
|
||||
[(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i))
|
||||
[(int) base_reg_class (regno_save_mode [i][1], PLUS, CONST_INT)], i))
|
||||
break;
|
||||
|
||||
if (i == FIRST_PSEUDO_REGISTER)
|
||||
abort ();
|
||||
gcc_assert (i < FIRST_PSEUDO_REGISTER);
|
||||
|
||||
addr_reg = gen_rtx_REG (Pmode, i);
|
||||
|
||||
@ -199,7 +195,7 @@ init_caller_save (void)
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
|
||||
if (HARD_REGNO_MODE_OK (i, mode))
|
||||
{
|
||||
{
|
||||
int ok;
|
||||
|
||||
/* Update the register number and modes of the register
|
||||
@ -216,7 +212,7 @@ init_caller_save (void)
|
||||
reg_restore_code[i][mode] = recog_memoized (restinsn);
|
||||
|
||||
/* Now extract both insns and see if we can meet their
|
||||
constraints. */
|
||||
constraints. */
|
||||
ok = (reg_save_code[i][mode] != -1
|
||||
&& reg_restore_code[i][mode] != -1);
|
||||
if (ok)
|
||||
@ -232,7 +228,7 @@ init_caller_save (void)
|
||||
reg_save_code[i][mode] = -1;
|
||||
reg_restore_code[i][mode] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reg_save_code[i][mode] = -1;
|
||||
@ -300,7 +296,7 @@ setup_save_areas (void)
|
||||
{
|
||||
unsigned int regno = reg_renumber[i];
|
||||
unsigned int endregno
|
||||
= regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i]));
|
||||
= regno + hard_regno_nregs[regno][GET_MODE (regno_reg_rtx[i])];
|
||||
|
||||
for (r = regno; r < endregno; r++)
|
||||
if (call_used_regs[r])
|
||||
@ -371,6 +367,10 @@ save_call_clobbered_regs (void)
|
||||
struct insn_chain *chain, *next;
|
||||
enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
|
||||
|
||||
/* Computed in mark_set_regs, holds all registers set by the current
|
||||
instruction. */
|
||||
HARD_REG_SET this_insn_sets;
|
||||
|
||||
CLEAR_HARD_REG_SET (hard_regs_saved);
|
||||
n_regs_saved = 0;
|
||||
|
||||
@ -381,10 +381,9 @@ save_call_clobbered_regs (void)
|
||||
|
||||
next = chain->next;
|
||||
|
||||
if (chain->is_caller_save_insn)
|
||||
abort ();
|
||||
gcc_assert (!chain->is_caller_save_insn);
|
||||
|
||||
if (GET_RTX_CLASS (code) == 'i')
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
/* If some registers have been saved, see if INSN references
|
||||
any of them. We must restore them before the insn if so. */
|
||||
@ -410,8 +409,9 @@ save_call_clobbered_regs (void)
|
||||
|
||||
if (code == CALL_INSN && ! find_reg_note (insn, REG_NORETURN, NULL))
|
||||
{
|
||||
int regno;
|
||||
unsigned regno;
|
||||
HARD_REG_SET hard_regs_to_save;
|
||||
reg_set_iterator rsi;
|
||||
|
||||
/* Use the register life information in CHAIN to compute which
|
||||
regs are live during the call. */
|
||||
@ -427,34 +427,34 @@ save_call_clobbered_regs (void)
|
||||
/* Look through all live pseudos, mark their hard registers
|
||||
and choose proper mode for saving. */
|
||||
EXECUTE_IF_SET_IN_REG_SET
|
||||
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno,
|
||||
{
|
||||
int r = reg_renumber[regno];
|
||||
int nregs;
|
||||
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
|
||||
{
|
||||
int r = reg_renumber[regno];
|
||||
int nregs;
|
||||
enum machine_mode mode;
|
||||
|
||||
if (r >= 0)
|
||||
{
|
||||
enum machine_mode mode;
|
||||
|
||||
nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
|
||||
mode = HARD_REGNO_CALLER_SAVE_MODE
|
||||
(r, nregs, PSEUDO_REGNO_MODE (regno));
|
||||
if (GET_MODE_BITSIZE (mode)
|
||||
> GET_MODE_BITSIZE (save_mode[r]))
|
||||
save_mode[r] = mode;
|
||||
while (nregs-- > 0)
|
||||
SET_HARD_REG_BIT (hard_regs_to_save, r + nregs);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
});
|
||||
gcc_assert (r >= 0);
|
||||
nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
|
||||
mode = HARD_REGNO_CALLER_SAVE_MODE
|
||||
(r, nregs, PSEUDO_REGNO_MODE (regno));
|
||||
if (GET_MODE_BITSIZE (mode)
|
||||
> GET_MODE_BITSIZE (save_mode[r]))
|
||||
save_mode[r] = mode;
|
||||
while (nregs-- > 0)
|
||||
SET_HARD_REG_BIT (hard_regs_to_save, r + nregs);
|
||||
}
|
||||
|
||||
/* Record all registers set in this call insn. These don't need
|
||||
to be saved. N.B. the call insn might set a subreg of a
|
||||
multi-hard-reg pseudo; then the pseudo is considered live
|
||||
during the call, but the subreg that is set isn't. */
|
||||
CLEAR_HARD_REG_SET (this_insn_sets);
|
||||
note_stores (PATTERN (insn), mark_set_regs, NULL);
|
||||
note_stores (PATTERN (insn), mark_set_regs, &this_insn_sets);
|
||||
/* Sibcalls are considered to set the return value,
|
||||
compare flow.c:propagate_one_insn. */
|
||||
if (SIBLING_CALL_P (insn) && current_function_return_rtx)
|
||||
mark_set_regs (current_function_return_rtx, NULL_RTX,
|
||||
&this_insn_sets);
|
||||
|
||||
/* Compute which hard regs must be saved before this call. */
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
|
||||
@ -484,41 +484,41 @@ save_call_clobbered_regs (void)
|
||||
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 += insert_restore (chain, JUMP_P (insn),
|
||||
regno, MOVE_MAX_WORDS, save_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Here from note_stores when an insn stores a value in a register.
|
||||
/* Here from note_stores, or directly from save_call_clobbered_regs, when
|
||||
an insn stores a value in a register.
|
||||
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
|
||||
mark_set_regs (rtx reg, rtx setter ATTRIBUTE_UNUSED,
|
||||
void *data ATTRIBUTE_UNUSED)
|
||||
mark_set_regs (rtx reg, rtx setter ATTRIBUTE_UNUSED, void *data)
|
||||
{
|
||||
int regno, endregno, i;
|
||||
enum machine_mode mode = GET_MODE (reg);
|
||||
HARD_REG_SET *this_insn_sets = data;
|
||||
|
||||
if (GET_CODE (reg) == SUBREG)
|
||||
{
|
||||
rtx inner = SUBREG_REG (reg);
|
||||
if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
|
||||
if (!REG_P (inner) || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
|
||||
return;
|
||||
|
||||
regno = subreg_hard_regno (reg, 1);
|
||||
regno = subreg_regno (reg);
|
||||
}
|
||||
else if (GET_CODE (reg) == REG
|
||||
else if (REG_P (reg)
|
||||
&& REGNO (reg) < FIRST_PSEUDO_REGISTER)
|
||||
regno = REGNO (reg);
|
||||
else
|
||||
return;
|
||||
|
||||
endregno = regno + HARD_REGNO_NREGS (regno, mode);
|
||||
endregno = regno + hard_regno_nregs[regno][mode];
|
||||
|
||||
for (i = regno; i < endregno; i++)
|
||||
SET_HARD_REG_BIT (this_insn_sets, i);
|
||||
SET_HARD_REG_BIT (*this_insn_sets, i);
|
||||
}
|
||||
|
||||
/* Here from note_stores when an insn stores a value in a register.
|
||||
@ -535,7 +535,7 @@ add_stored_regs (rtx reg, rtx setter, void *data)
|
||||
if (GET_CODE (setter) == CLOBBER)
|
||||
return;
|
||||
|
||||
if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
|
||||
if (GET_CODE (reg) == SUBREG && REG_P (SUBREG_REG (reg)))
|
||||
{
|
||||
offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
|
||||
GET_MODE (SUBREG_REG (reg)),
|
||||
@ -544,11 +544,11 @@ add_stored_regs (rtx reg, rtx setter, void *data)
|
||||
reg = SUBREG_REG (reg);
|
||||
}
|
||||
|
||||
if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
||||
if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
|
||||
return;
|
||||
|
||||
regno = REGNO (reg) + offset;
|
||||
endregno = regno + HARD_REGNO_NREGS (regno, mode);
|
||||
endregno = regno + hard_regno_nregs[regno][mode];
|
||||
|
||||
for (i = regno; i < endregno; i++)
|
||||
SET_REGNO_REG_SET ((regset) data, i);
|
||||
@ -570,7 +570,7 @@ mark_referenced_regs (rtx x)
|
||||
code = GET_CODE (x);
|
||||
if ((code == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
|
||||
|| code == PC || code == CC0
|
||||
|| (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
|
||||
|| (code == SUBREG && REG_P (SUBREG_REG (x))
|
||||
&& REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER
|
||||
/* If we're setting only part of a multi-word register,
|
||||
we shall mark it as referenced, because the words
|
||||
@ -595,7 +595,7 @@ mark_referenced_regs (rtx x)
|
||||
|
||||
if (hardregno >= 0)
|
||||
{
|
||||
int nregs = HARD_REGNO_NREGS (hardregno, GET_MODE (x));
|
||||
int nregs = hard_regno_nregs[hardregno][GET_MODE (x)];
|
||||
while (nregs-- > 0)
|
||||
SET_HARD_REG_BIT (referenced_regs, hardregno + nregs);
|
||||
}
|
||||
@ -644,15 +644,13 @@ insert_restore (struct insn_chain *chain, int before_p, int regno,
|
||||
struct insn_chain *new;
|
||||
rtx mem;
|
||||
|
||||
/* 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 ();
|
||||
/* 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 here instead. This will remove
|
||||
one step in debugging such problems. */
|
||||
gcc_assert (regno_save_mem[regno][1]);
|
||||
|
||||
/* Get the pattern to emit and update our status.
|
||||
|
||||
@ -683,8 +681,10 @@ insert_restore (struct insn_chain *chain, int before_p, int regno,
|
||||
mem = regno_save_mem [regno][numregs];
|
||||
if (save_mode [regno] != VOIDmode
|
||||
&& save_mode [regno] != GET_MODE (mem)
|
||||
&& numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno]))
|
||||
&& numregs == (unsigned int) hard_regno_nregs[regno][save_mode [regno]])
|
||||
mem = adjust_address (mem, save_mode[regno], 0);
|
||||
else
|
||||
mem = copy_rtx (mem);
|
||||
pat = gen_rtx_SET (VOIDmode,
|
||||
gen_rtx_REG (GET_MODE (mem),
|
||||
regno), mem);
|
||||
@ -717,15 +717,13 @@ insert_save (struct insn_chain *chain, int before_p, int regno,
|
||||
struct insn_chain *new;
|
||||
rtx mem;
|
||||
|
||||
/* 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
|
||||
/* 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 here. This will remove one
|
||||
step in debugging such problems. */
|
||||
|
||||
if (regno_save_mem[regno][1] == 0)
|
||||
abort ();
|
||||
gcc_assert (regno_save_mem[regno][1]);
|
||||
|
||||
/* Get the pattern to emit and update our status.
|
||||
|
||||
@ -755,8 +753,10 @@ insert_save (struct insn_chain *chain, int before_p, int regno,
|
||||
mem = regno_save_mem [regno][numregs];
|
||||
if (save_mode [regno] != VOIDmode
|
||||
&& save_mode [regno] != GET_MODE (mem)
|
||||
&& numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno]))
|
||||
&& numregs == (unsigned int) hard_regno_nregs[regno][save_mode [regno]])
|
||||
mem = adjust_address (mem, save_mode[regno], 0);
|
||||
else
|
||||
mem = copy_rtx (mem);
|
||||
pat = gen_rtx_SET (VOIDmode, mem,
|
||||
gen_rtx_REG (GET_MODE (mem),
|
||||
regno));
|
||||
@ -789,7 +789,7 @@ insert_one_insn (struct insn_chain *chain, int before_p, int code, rtx pat)
|
||||
isn't a problem. We do, however, assume here that CALL_INSNs don't
|
||||
reference CC0. Guard against non-INSN's like CODE_LABEL. */
|
||||
|
||||
if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
|
||||
if ((NONJUMP_INSN_P (insn) || JUMP_P (insn))
|
||||
&& before_p
|
||||
&& reg_referenced_p (cc0_rtx, PATTERN (insn)))
|
||||
chain = chain->prev, insn = chain->insn;
|
||||
@ -820,15 +820,13 @@ insert_one_insn (struct insn_chain *chain, int before_p, int code, rtx pat)
|
||||
rtx reg = XEXP (link, 0);
|
||||
int regno, i;
|
||||
|
||||
if (GET_CODE (reg) != REG)
|
||||
abort ();
|
||||
|
||||
gcc_assert (REG_P (reg));
|
||||
regno = REGNO (reg);
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
regno = reg_renumber[regno];
|
||||
if (regno < 0)
|
||||
continue;
|
||||
for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
|
||||
for (i = hard_regno_nregs[regno][GET_MODE (reg)] - 1;
|
||||
i >= 0; i--)
|
||||
SET_REGNO_REG_SET (&new->live_throughout, regno + i);
|
||||
}
|
||||
@ -849,7 +847,7 @@ insert_one_insn (struct insn_chain *chain, int before_p, int code, rtx pat)
|
||||
registers from the live sets, and observe REG_UNUSED notes. */
|
||||
COPY_REG_SET (&new->live_throughout, &chain->live_throughout);
|
||||
/* Registers that are set in CHAIN->INSN live in the new insn.
|
||||
(Unless there is a REG_UNUSED note for them, but we don't
|
||||
(Unless there is a REG_UNUSED note for them, but we don't
|
||||
look for them here.) */
|
||||
note_stores (PATTERN (chain->insn), add_stored_regs,
|
||||
&new->live_throughout);
|
||||
|
1739
contrib/gcc/calls.c
1739
contrib/gcc/calls.c
File diff suppressed because it is too large
Load Diff
1188
contrib/gcc/cfg.c
1188
contrib/gcc/cfg.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
||||
/* Control flow graph building code for GNU compiler.
|
||||
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -16,8 +16,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* find_basic_blocks divides the current function's rtl into basic
|
||||
blocks and constructs the CFG. The blocks are recorded in the
|
||||
@ -28,9 +28,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
Available functionality:
|
||||
- CFG construction
|
||||
find_basic_blocks
|
||||
- Local CFG construction
|
||||
find_sub_basic_blocks */
|
||||
find_basic_blocks */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -50,10 +48,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
|
||||
static int count_basic_blocks (rtx);
|
||||
static void find_basic_blocks_1 (rtx);
|
||||
static rtx find_label_refs (rtx, rtx);
|
||||
static void make_edges (rtx, basic_block, basic_block, int);
|
||||
static void make_label_edge (sbitmap *, basic_block, rtx, int);
|
||||
static void make_eh_edge (sbitmap *, basic_block, rtx);
|
||||
static void make_edges (basic_block, basic_block, int);
|
||||
static void make_label_edge (sbitmap, basic_block, rtx, int);
|
||||
static void find_bb_boundaries (basic_block);
|
||||
static void compute_outgoing_frequencies (basic_block);
|
||||
|
||||
@ -68,7 +64,7 @@ inside_basic_block_p (rtx insn)
|
||||
case CODE_LABEL:
|
||||
/* Avoid creating of basic block for jumptables. */
|
||||
return (NEXT_INSN (insn) == 0
|
||||
|| GET_CODE (NEXT_INSN (insn)) != JUMP_INSN
|
||||
|| !JUMP_P (NEXT_INSN (insn))
|
||||
|| (GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_VEC
|
||||
&& GET_CODE (PATTERN (NEXT_INSN (insn))) != ADDR_DIFF_VEC));
|
||||
|
||||
@ -85,7 +81,7 @@ inside_basic_block_p (rtx insn)
|
||||
return false;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,6 +105,12 @@ control_flow_insn_p (rtx insn)
|
||||
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC);
|
||||
|
||||
case CALL_INSN:
|
||||
/* Noreturn and sibling call instructions terminate the basic blocks
|
||||
(but only if they happen unconditionally). */
|
||||
if ((SIBLING_CALL_P (insn)
|
||||
|| find_reg_note (insn, REG_NORETURN, 0))
|
||||
&& GET_CODE (PATTERN (insn)) != COND_EXEC)
|
||||
return true;
|
||||
/* Call insn may return to the nonlocal goto handler. */
|
||||
return ((nonlocal_goto_handler_labels
|
||||
&& (0 == (note = find_reg_note (insn, REG_EH_REGION,
|
||||
@ -118,16 +120,21 @@ control_flow_insn_p (rtx insn)
|
||||
|| can_throw_internal (insn));
|
||||
|
||||
case INSN:
|
||||
/* Treat trap instructions like noreturn calls (same provision). */
|
||||
if (GET_CODE (PATTERN (insn)) == TRAP_IF
|
||||
&& XEXP (PATTERN (insn), 0) == const1_rtx)
|
||||
return true;
|
||||
|
||||
return (flag_non_call_exceptions && can_throw_internal (insn));
|
||||
|
||||
case BARRIER:
|
||||
/* It is nonsense to reach barrier when looking for the
|
||||
end of basic block, but before dead code is eliminated
|
||||
this may happen. */
|
||||
end of basic block, but before dead code is eliminated
|
||||
this may happen. */
|
||||
return false;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,15 +143,15 @@ control_flow_insn_p (rtx insn)
|
||||
static int
|
||||
count_basic_blocks (rtx f)
|
||||
{
|
||||
int count = 0;
|
||||
int count = NUM_FIXED_BLOCKS;
|
||||
bool saw_insn = false;
|
||||
rtx insn;
|
||||
|
||||
for (insn = f; insn; insn = NEXT_INSN (insn))
|
||||
{
|
||||
/* Code labels and barriers causes current basic block to be
|
||||
terminated at previous real insn. */
|
||||
if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
|
||||
terminated at previous real insn. */
|
||||
if ((LABEL_P (insn) || BARRIER_P (insn))
|
||||
&& saw_insn)
|
||||
count++, saw_insn = false;
|
||||
|
||||
@ -162,59 +169,14 @@ count_basic_blocks (rtx f)
|
||||
|
||||
/* The rest of the compiler works a bit smoother when we don't have to
|
||||
check for the edge case of do-nothing functions with no basic blocks. */
|
||||
if (count == 0)
|
||||
if (count == NUM_FIXED_BLOCKS)
|
||||
{
|
||||
emit_insn (gen_rtx_USE (VOIDmode, const0_rtx));
|
||||
count = 1;
|
||||
count = NUM_FIXED_BLOCKS + 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* Scan a list of insns for labels referred to other than by jumps.
|
||||
This is used to scan the alternatives of a call placeholder. */
|
||||
|
||||
static rtx
|
||||
find_label_refs (rtx f, rtx lvl)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
for (insn = f; insn; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn) && GET_CODE (insn) != JUMP_INSN)
|
||||
{
|
||||
rtx note;
|
||||
|
||||
/* Make a list of all labels referred to other than by jumps
|
||||
(which just don't have the REG_LABEL notes).
|
||||
|
||||
Make a special exception for labels followed by an ADDR*VEC,
|
||||
as this would be a part of the tablejump setup code.
|
||||
|
||||
Make a special exception to registers loaded with label
|
||||
values just before jump insns that use them. */
|
||||
|
||||
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
|
||||
if (REG_NOTE_KIND (note) == REG_LABEL)
|
||||
{
|
||||
rtx lab = XEXP (note, 0), next;
|
||||
|
||||
if ((next = next_nonnote_insn (lab)) != NULL
|
||||
&& GET_CODE (next) == JUMP_INSN
|
||||
&& (GET_CODE (PATTERN (next)) == ADDR_VEC
|
||||
|| GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
|
||||
;
|
||||
else if (GET_CODE (lab) == NOTE)
|
||||
;
|
||||
else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
|
||||
&& find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
|
||||
;
|
||||
else
|
||||
lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
|
||||
}
|
||||
}
|
||||
|
||||
return lvl;
|
||||
}
|
||||
|
||||
/* Create an edge between two basic blocks. FLAGS are auxiliary information
|
||||
about the edge that is accumulated between calls. */
|
||||
@ -222,10 +184,9 @@ find_label_refs (rtx f, rtx lvl)
|
||||
/* Create an edge from a basic block to a label. */
|
||||
|
||||
static void
|
||||
make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
|
||||
make_label_edge (sbitmap edge_cache, basic_block src, rtx label, int flags)
|
||||
{
|
||||
if (GET_CODE (label) != CODE_LABEL)
|
||||
abort ();
|
||||
gcc_assert (LABEL_P (label));
|
||||
|
||||
/* If the label was never emitted, this insn is junk, but avoid a
|
||||
crash trying to refer to BLOCK_FOR_INSN (label). This can happen
|
||||
@ -240,10 +201,10 @@ make_label_edge (sbitmap *edge_cache, basic_block src, rtx label, int flags)
|
||||
|
||||
/* Create the edges generated by INSN in REGION. */
|
||||
|
||||
static void
|
||||
make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
|
||||
void
|
||||
rtl_make_eh_edge (sbitmap edge_cache, basic_block src, rtx insn)
|
||||
{
|
||||
int is_call = GET_CODE (insn) == CALL_INSN ? EDGE_ABNORMAL_CALL : 0;
|
||||
int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0;
|
||||
rtx handlers, i;
|
||||
|
||||
handlers = reachable_handlers (insn);
|
||||
@ -255,55 +216,78 @@ make_eh_edge (sbitmap *edge_cache, basic_block src, rtx insn)
|
||||
free_INSN_LIST_list (&handlers);
|
||||
}
|
||||
|
||||
/* Identify the edges between basic blocks MIN to MAX.
|
||||
/* States of basic block as seen by find_many_sub_basic_blocks. */
|
||||
enum state {
|
||||
/* Basic blocks created via split_block belong to this state.
|
||||
make_edges will examine these basic blocks to see if we need to
|
||||
create edges going out of them. */
|
||||
BLOCK_NEW = 0,
|
||||
|
||||
NONLOCAL_LABEL_LIST is a list of non-local labels in the function. Blocks
|
||||
that are otherwise unreachable may be reachable with a non-local goto.
|
||||
/* Basic blocks that do not need examining belong to this state.
|
||||
These blocks will be left intact. In particular, make_edges will
|
||||
not create edges going out of these basic blocks. */
|
||||
BLOCK_ORIGINAL,
|
||||
|
||||
BB_EH_END is an array indexed by basic block number in which we record
|
||||
the list of exception regions active at the end of the basic block. */
|
||||
/* Basic blocks that may need splitting (due to a label appearing in
|
||||
the middle, etc) belong to this state. After splitting them,
|
||||
make_edges will create edges going out of them as needed. */
|
||||
BLOCK_TO_SPLIT
|
||||
};
|
||||
|
||||
#define STATE(BB) (enum state) ((size_t) (BB)->aux)
|
||||
#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
|
||||
|
||||
/* Used internally by purge_dead_tablejump_edges, ORed into state. */
|
||||
#define BLOCK_USED_BY_TABLEJUMP 32
|
||||
#define FULL_STATE(BB) ((size_t) (BB)->aux)
|
||||
|
||||
/* Identify the edges going out of basic blocks between MIN and MAX,
|
||||
inclusive, that have their states set to BLOCK_NEW or
|
||||
BLOCK_TO_SPLIT.
|
||||
|
||||
UPDATE_P should be nonzero if we are updating CFG and zero if we
|
||||
are building CFG from scratch. */
|
||||
|
||||
static void
|
||||
make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p)
|
||||
make_edges (basic_block min, basic_block max, int update_p)
|
||||
{
|
||||
basic_block bb;
|
||||
sbitmap *edge_cache = NULL;
|
||||
|
||||
/* Assume no computed jump; revise as we create edges. */
|
||||
current_function_has_computed_jump = 0;
|
||||
sbitmap edge_cache = NULL;
|
||||
|
||||
/* Heavy use of computed goto in machine-generated code can lead to
|
||||
nearly fully-connected CFGs. In that case we spend a significant
|
||||
amount of time searching the edge lists for duplicates. */
|
||||
if (forced_labels || label_value_list || cfun->max_jumptable_ents > 100)
|
||||
{
|
||||
edge_cache = sbitmap_vector_alloc (last_basic_block, last_basic_block);
|
||||
sbitmap_vector_zero (edge_cache, last_basic_block);
|
||||
|
||||
if (update_p)
|
||||
FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
|
||||
{
|
||||
edge e;
|
||||
|
||||
for (e = bb->succ; e ; e = e->succ_next)
|
||||
if (e->dest != EXIT_BLOCK_PTR)
|
||||
SET_BIT (edge_cache[bb->index], e->dest->index);
|
||||
}
|
||||
}
|
||||
if (forced_labels || cfun->max_jumptable_ents > 100)
|
||||
edge_cache = sbitmap_alloc (last_basic_block);
|
||||
|
||||
/* By nature of the way these get numbered, ENTRY_BLOCK_PTR->next_bb block
|
||||
is always the entry. */
|
||||
if (min == ENTRY_BLOCK_PTR->next_bb)
|
||||
cached_make_edge (edge_cache, ENTRY_BLOCK_PTR, min,
|
||||
EDGE_FALLTHRU);
|
||||
make_edge (ENTRY_BLOCK_PTR, min, EDGE_FALLTHRU);
|
||||
|
||||
FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
|
||||
{
|
||||
rtx insn, x;
|
||||
enum rtx_code code;
|
||||
int force_fallthru = 0;
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
if (GET_CODE (BB_HEAD (bb)) == CODE_LABEL
|
||||
if (STATE (bb) == BLOCK_ORIGINAL)
|
||||
continue;
|
||||
|
||||
/* If we have an edge cache, cache edges going out of BB. */
|
||||
if (edge_cache)
|
||||
{
|
||||
sbitmap_zero (edge_cache);
|
||||
if (update_p)
|
||||
{
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
if (e->dest != EXIT_BLOCK_PTR)
|
||||
SET_BIT (edge_cache, e->dest->index);
|
||||
}
|
||||
}
|
||||
|
||||
if (LABEL_P (BB_HEAD (bb))
|
||||
&& LABEL_ALT_ENTRY_P (BB_HEAD (bb)))
|
||||
cached_make_edge (NULL, ENTRY_BLOCK_PTR, bb, 0);
|
||||
|
||||
@ -320,7 +304,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
|
||||
|
||||
/* Recognize exception handling placeholders. */
|
||||
if (GET_CODE (PATTERN (insn)) == RESX)
|
||||
make_eh_edge (edge_cache, bb, insn);
|
||||
rtl_make_eh_edge (edge_cache, bb, insn);
|
||||
|
||||
/* Recognize a non-local goto as a branch outside the
|
||||
current function. */
|
||||
@ -351,23 +335,12 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
|
||||
&& GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
|
||||
make_label_edge (edge_cache, bb,
|
||||
XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
|
||||
|
||||
#ifdef CASE_DROPS_THROUGH
|
||||
/* Silly VAXen. The ADDR_VEC is going to be in the way of
|
||||
us naturally detecting fallthru into the next block. */
|
||||
force_fallthru = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* If this is a computed jump, then mark it as reaching
|
||||
everything on the label_value_list and forced_labels list. */
|
||||
everything on the forced_labels list. */
|
||||
else if (computed_jump_p (insn))
|
||||
{
|
||||
current_function_has_computed_jump = 1;
|
||||
|
||||
for (x = label_value_list; x; x = XEXP (x, 1))
|
||||
make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
|
||||
|
||||
for (x = forced_labels; x; x = XEXP (x, 1))
|
||||
make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
|
||||
}
|
||||
@ -379,8 +352,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
|
||||
/* Otherwise, we have a plain conditional or unconditional jump. */
|
||||
else
|
||||
{
|
||||
if (! JUMP_LABEL (insn))
|
||||
abort ();
|
||||
gcc_assert (JUMP_LABEL (insn));
|
||||
make_label_edge (edge_cache, bb, JUMP_LABEL (insn), 0);
|
||||
}
|
||||
}
|
||||
@ -400,7 +372,7 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
|
||||
else if (code == CALL_INSN || flag_non_call_exceptions)
|
||||
{
|
||||
/* Add any appropriate EH edges. */
|
||||
make_eh_edge (edge_cache, bb, insn);
|
||||
rtl_make_eh_edge (edge_cache, bb, insn);
|
||||
|
||||
if (code == CALL_INSN && nonlocal_goto_handler_labels)
|
||||
{
|
||||
@ -424,16 +396,20 @@ make_edges (rtx label_value_list, basic_block min, basic_block max, int update_p
|
||||
|
||||
/* Find out if we can drop through to the next block. */
|
||||
insn = NEXT_INSN (insn);
|
||||
e = find_edge (bb, EXIT_BLOCK_PTR);
|
||||
if (e && e->flags & EDGE_FALLTHRU)
|
||||
insn = NULL;
|
||||
|
||||
while (insn
|
||||
&& GET_CODE (insn) == NOTE
|
||||
&& NOTE_P (insn)
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
|
||||
insn = NEXT_INSN (insn);
|
||||
|
||||
if (!insn || (bb->next_bb == EXIT_BLOCK_PTR && force_fallthru))
|
||||
if (!insn)
|
||||
cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
|
||||
else if (bb->next_bb != EXIT_BLOCK_PTR)
|
||||
{
|
||||
if (force_fallthru || insn == BB_HEAD (bb->next_bb))
|
||||
if (insn == BB_HEAD (bb->next_bb))
|
||||
cached_make_edge (edge_cache, bb, bb->next_bb, EDGE_FALLTHRU);
|
||||
}
|
||||
}
|
||||
@ -452,8 +428,6 @@ find_basic_blocks_1 (rtx f)
|
||||
{
|
||||
rtx insn, next;
|
||||
rtx bb_note = NULL_RTX;
|
||||
rtx lvl = NULL_RTX;
|
||||
rtx trll = NULL_RTX;
|
||||
rtx head = NULL_RTX;
|
||||
rtx end = NULL_RTX;
|
||||
basic_block prev = ENTRY_BLOCK_PTR;
|
||||
@ -470,7 +444,7 @@ find_basic_blocks_1 (rtx f)
|
||||
|
||||
next = NEXT_INSN (insn);
|
||||
|
||||
if ((GET_CODE (insn) == CODE_LABEL || GET_CODE (insn) == BARRIER)
|
||||
if ((LABEL_P (insn) || BARRIER_P (insn))
|
||||
&& head)
|
||||
{
|
||||
prev = create_basic_block_structure (head, end, bb_note, prev);
|
||||
@ -514,57 +488,13 @@ find_basic_blocks_1 (rtx f)
|
||||
|
||||
case CODE_LABEL:
|
||||
case JUMP_INSN:
|
||||
case CALL_INSN:
|
||||
case INSN:
|
||||
case BARRIER:
|
||||
break;
|
||||
|
||||
case CALL_INSN:
|
||||
if (GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
|
||||
{
|
||||
/* Scan each of the alternatives for label refs. */
|
||||
lvl = find_label_refs (XEXP (PATTERN (insn), 0), lvl);
|
||||
lvl = find_label_refs (XEXP (PATTERN (insn), 1), lvl);
|
||||
lvl = find_label_refs (XEXP (PATTERN (insn), 2), lvl);
|
||||
/* Record its tail recursion label, if any. */
|
||||
if (XEXP (PATTERN (insn), 3) != NULL_RTX)
|
||||
trll = alloc_EXPR_LIST (0, XEXP (PATTERN (insn), 3), trll);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
|
||||
{
|
||||
rtx note;
|
||||
|
||||
/* Make a list of all labels referred to other than by jumps.
|
||||
|
||||
Make a special exception for labels followed by an ADDR*VEC,
|
||||
as this would be a part of the tablejump setup code.
|
||||
|
||||
Make a special exception to registers loaded with label
|
||||
values just before jump insns that use them. */
|
||||
|
||||
for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
|
||||
if (REG_NOTE_KIND (note) == REG_LABEL)
|
||||
{
|
||||
rtx lab = XEXP (note, 0), next;
|
||||
|
||||
if ((next = next_nonnote_insn (lab)) != NULL
|
||||
&& GET_CODE (next) == JUMP_INSN
|
||||
&& (GET_CODE (PATTERN (next)) == ADDR_VEC
|
||||
|| GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC))
|
||||
;
|
||||
else if (GET_CODE (lab) == NOTE)
|
||||
;
|
||||
else if (GET_CODE (NEXT_INSN (insn)) == JUMP_INSN
|
||||
&& find_reg_note (NEXT_INSN (insn), REG_LABEL, lab))
|
||||
;
|
||||
else
|
||||
lvl = alloc_EXPR_LIST (0, XEXP (note, 0), lvl);
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -573,22 +503,17 @@ find_basic_blocks_1 (rtx f)
|
||||
else if (bb_note)
|
||||
delete_insn (bb_note);
|
||||
|
||||
if (last_basic_block != n_basic_blocks)
|
||||
abort ();
|
||||
gcc_assert (last_basic_block == n_basic_blocks);
|
||||
|
||||
label_value_list = lvl;
|
||||
tail_recursion_label_list = trll;
|
||||
clear_aux_for_blocks ();
|
||||
}
|
||||
|
||||
|
||||
/* Find basic blocks of the current function.
|
||||
F is the first insn of the function and NREGS the number of register
|
||||
numbers in use. */
|
||||
F is the first insn of the function. */
|
||||
|
||||
void
|
||||
find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
|
||||
FILE *file ATTRIBUTE_UNUSED)
|
||||
find_basic_blocks (rtx f)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
@ -605,14 +530,15 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
|
||||
FOR_EACH_BB (bb)
|
||||
bb->aux = NULL;
|
||||
|
||||
VARRAY_FREE (basic_block_info);
|
||||
basic_block_info = NULL;
|
||||
}
|
||||
|
||||
n_basic_blocks = count_basic_blocks (f);
|
||||
last_basic_block = 0;
|
||||
last_basic_block = NUM_FIXED_BLOCKS;
|
||||
ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
|
||||
EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
|
||||
|
||||
|
||||
/* Size the basic block table. The actual structures will be allocated
|
||||
by find_basic_blocks_1, since we want to keep the structure pointers
|
||||
stable across calls to find_basic_blocks. */
|
||||
@ -621,12 +547,23 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
|
||||
instructions at all until close to the end of compilation when we
|
||||
actually lay them out. */
|
||||
|
||||
VARRAY_BB_INIT (basic_block_info, n_basic_blocks, "basic_block_info");
|
||||
basic_block_info = VEC_alloc (basic_block, gc, n_basic_blocks);
|
||||
VEC_safe_grow (basic_block, gc, basic_block_info, n_basic_blocks);
|
||||
memset (VEC_address (basic_block, basic_block_info), 0,
|
||||
sizeof (basic_block) * n_basic_blocks);
|
||||
SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
|
||||
SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
|
||||
|
||||
find_basic_blocks_1 (f);
|
||||
|
||||
profile_status = PROFILE_ABSENT;
|
||||
|
||||
/* Tell make_edges to examine every block for out-going edges. */
|
||||
FOR_EACH_BB (bb)
|
||||
SET_STATE (bb, BLOCK_NEW);
|
||||
|
||||
/* Discover the edges of our cfg. */
|
||||
make_edges (label_value_list, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
|
||||
make_edges (ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, 0);
|
||||
|
||||
/* Do very simple cleanup now, for the benefit of code that runs between
|
||||
here and cleanup_cfg, e.g. thread_prologue_and_epilogue_insns. */
|
||||
@ -638,11 +575,58 @@ find_basic_blocks (rtx f, int nregs ATTRIBUTE_UNUSED,
|
||||
timevar_pop (TV_CFG);
|
||||
}
|
||||
|
||||
/* State of basic block as seen by find_sub_basic_blocks. */
|
||||
enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
|
||||
static void
|
||||
mark_tablejump_edge (rtx label)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
#define STATE(BB) (enum state) ((size_t) (BB)->aux)
|
||||
#define SET_STATE(BB, STATE) ((BB)->aux = (void *) (size_t) (STATE))
|
||||
gcc_assert (LABEL_P (label));
|
||||
/* See comment in make_label_edge. */
|
||||
if (INSN_UID (label) == 0)
|
||||
return;
|
||||
bb = BLOCK_FOR_INSN (label);
|
||||
SET_STATE (bb, FULL_STATE (bb) | BLOCK_USED_BY_TABLEJUMP);
|
||||
}
|
||||
|
||||
static void
|
||||
purge_dead_tablejump_edges (basic_block bb, rtx table)
|
||||
{
|
||||
rtx insn = BB_END (bb), tmp;
|
||||
rtvec vec;
|
||||
int j;
|
||||
edge_iterator ei;
|
||||
edge e;
|
||||
|
||||
if (GET_CODE (PATTERN (table)) == ADDR_VEC)
|
||||
vec = XVEC (PATTERN (table), 0);
|
||||
else
|
||||
vec = XVEC (PATTERN (table), 1);
|
||||
|
||||
for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
|
||||
mark_tablejump_edge (XEXP (RTVEC_ELT (vec, j), 0));
|
||||
|
||||
/* Some targets (eg, ARM) emit a conditional jump that also
|
||||
contains the out-of-range target. Scan for these and
|
||||
add an edge if necessary. */
|
||||
if ((tmp = single_set (insn)) != NULL
|
||||
&& SET_DEST (tmp) == pc_rtx
|
||||
&& GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
|
||||
&& GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
|
||||
mark_tablejump_edge (XEXP (XEXP (SET_SRC (tmp), 2), 0));
|
||||
|
||||
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
|
||||
{
|
||||
if (FULL_STATE (e->dest) & BLOCK_USED_BY_TABLEJUMP)
|
||||
SET_STATE (e->dest, FULL_STATE (e->dest)
|
||||
& ~(size_t) BLOCK_USED_BY_TABLEJUMP);
|
||||
else if (!(e->flags & (EDGE_ABNORMAL | EDGE_EH)))
|
||||
{
|
||||
remove_edge (e);
|
||||
continue;
|
||||
}
|
||||
ei_next (&ei);
|
||||
}
|
||||
}
|
||||
|
||||
/* Scan basic block BB for possible BB boundaries inside the block
|
||||
and create new basic blocks in the progress. */
|
||||
@ -650,15 +634,17 @@ enum state {BLOCK_NEW = 0, BLOCK_ORIGINAL, BLOCK_TO_SPLIT};
|
||||
static void
|
||||
find_bb_boundaries (basic_block bb)
|
||||
{
|
||||
basic_block orig_bb = bb;
|
||||
rtx insn = BB_HEAD (bb);
|
||||
rtx end = BB_END (bb);
|
||||
rtx table;
|
||||
rtx flow_transfer_insn = NULL_RTX;
|
||||
edge fallthru = NULL;
|
||||
|
||||
if (insn == BB_END (bb))
|
||||
return;
|
||||
|
||||
if (GET_CODE (insn) == CODE_LABEL)
|
||||
if (LABEL_P (insn))
|
||||
insn = NEXT_INSN (insn);
|
||||
|
||||
/* Scan insn chain and try to find new basic block boundaries. */
|
||||
@ -708,6 +694,11 @@ find_bb_boundaries (basic_block bb)
|
||||
followed by cleanup at fallthru edge, so the outgoing edges may
|
||||
be dead. */
|
||||
purge_dead_edges (bb);
|
||||
|
||||
/* purge_dead_edges doesn't handle tablejump's, but if we have split the
|
||||
basic block, we might need to kill some edges. */
|
||||
if (bb != orig_bb && tablejump_p (BB_END (bb), NULL, &table))
|
||||
purge_dead_tablejump_edges (bb, table);
|
||||
}
|
||||
|
||||
/* Assume that frequency of basic block B is known. Compute frequencies
|
||||
@ -717,35 +708,44 @@ static void
|
||||
compute_outgoing_frequencies (basic_block b)
|
||||
{
|
||||
edge e, f;
|
||||
edge_iterator ei;
|
||||
|
||||
if (b->succ && b->succ->succ_next && !b->succ->succ_next->succ_next)
|
||||
if (EDGE_COUNT (b->succs) == 2)
|
||||
{
|
||||
rtx note = find_reg_note (BB_END (b), REG_BR_PROB, NULL);
|
||||
int probability;
|
||||
|
||||
if (!note)
|
||||
return;
|
||||
|
||||
probability = INTVAL (XEXP (note, 0));
|
||||
e = BRANCH_EDGE (b);
|
||||
e->probability = probability;
|
||||
e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
|
||||
/ REG_BR_PROB_BASE);
|
||||
f = FALLTHRU_EDGE (b);
|
||||
f->probability = REG_BR_PROB_BASE - probability;
|
||||
f->count = b->count - e->count;
|
||||
if (note)
|
||||
{
|
||||
probability = INTVAL (XEXP (note, 0));
|
||||
e = BRANCH_EDGE (b);
|
||||
e->probability = probability;
|
||||
e->count = ((b->count * probability + REG_BR_PROB_BASE / 2)
|
||||
/ REG_BR_PROB_BASE);
|
||||
f = FALLTHRU_EDGE (b);
|
||||
f->probability = REG_BR_PROB_BASE - probability;
|
||||
f->count = b->count - e->count;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (b->succ && !b->succ->succ_next)
|
||||
if (single_succ_p (b))
|
||||
{
|
||||
e = b->succ;
|
||||
e = single_succ_edge (b);
|
||||
e->probability = REG_BR_PROB_BASE;
|
||||
e->count = b->count;
|
||||
return;
|
||||
}
|
||||
guess_outgoing_edge_probabilities (b);
|
||||
if (b->count)
|
||||
FOR_EACH_EDGE (e, ei, b->succs)
|
||||
e->count = ((b->count * e->probability + REG_BR_PROB_BASE / 2)
|
||||
/ REG_BR_PROB_BASE);
|
||||
}
|
||||
|
||||
/* Assume that someone emitted code with control flow instructions to the
|
||||
basic block. Update the data structure. */
|
||||
/* Assume that some pass has inserted labels or control flow
|
||||
instructions within a basic block. Split basic blocks as needed
|
||||
and create edges. */
|
||||
|
||||
void
|
||||
find_many_sub_basic_blocks (sbitmap blocks)
|
||||
@ -771,67 +771,32 @@ find_many_sub_basic_blocks (sbitmap blocks)
|
||||
|
||||
/* Now re-scan and wire in all edges. This expect simple (conditional)
|
||||
jumps at the end of each new basic blocks. */
|
||||
make_edges (NULL, min, max, 1);
|
||||
make_edges (min, max, 1);
|
||||
|
||||
/* Update branch probabilities. Expect only (un)conditional jumps
|
||||
to be created with only the forward edges. */
|
||||
FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
|
||||
{
|
||||
edge e;
|
||||
if (profile_status != PROFILE_ABSENT)
|
||||
FOR_BB_BETWEEN (bb, min, max->next_bb, next_bb)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
if (STATE (bb) == BLOCK_ORIGINAL)
|
||||
continue;
|
||||
if (STATE (bb) == BLOCK_NEW)
|
||||
{
|
||||
bb->count = 0;
|
||||
bb->frequency = 0;
|
||||
for (e = bb->pred; e; e = e->pred_next)
|
||||
{
|
||||
bb->count += e->count;
|
||||
bb->frequency += EDGE_FREQUENCY (e);
|
||||
}
|
||||
}
|
||||
if (STATE (bb) == BLOCK_ORIGINAL)
|
||||
continue;
|
||||
if (STATE (bb) == BLOCK_NEW)
|
||||
{
|
||||
bb->count = 0;
|
||||
bb->frequency = 0;
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
{
|
||||
bb->count += e->count;
|
||||
bb->frequency += EDGE_FREQUENCY (e);
|
||||
}
|
||||
}
|
||||
|
||||
compute_outgoing_frequencies (bb);
|
||||
}
|
||||
compute_outgoing_frequencies (bb);
|
||||
}
|
||||
|
||||
FOR_EACH_BB (bb)
|
||||
SET_STATE (bb, 0);
|
||||
}
|
||||
|
||||
/* Like above but for single basic block only. */
|
||||
|
||||
void
|
||||
find_sub_basic_blocks (basic_block bb)
|
||||
{
|
||||
basic_block min, max, b;
|
||||
basic_block next = bb->next_bb;
|
||||
|
||||
min = bb;
|
||||
find_bb_boundaries (bb);
|
||||
max = next->prev_bb;
|
||||
|
||||
/* Now re-scan and wire in all edges. This expect simple (conditional)
|
||||
jumps at the end of each new basic blocks. */
|
||||
make_edges (NULL, min, max, 1);
|
||||
|
||||
/* Update branch probabilities. Expect only (un)conditional jumps
|
||||
to be created with only the forward edges. */
|
||||
FOR_BB_BETWEEN (b, min, max->next_bb, next_bb)
|
||||
{
|
||||
edge e;
|
||||
|
||||
if (b != min)
|
||||
{
|
||||
b->count = 0;
|
||||
b->frequency = 0;
|
||||
for (e = b->pred; e; e = e->pred_next)
|
||||
{
|
||||
b->count += e->count;
|
||||
b->frequency += EDGE_FREQUENCY (e);
|
||||
}
|
||||
}
|
||||
|
||||
compute_outgoing_frequencies (b);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
1732
contrib/gcc/cfgexpand.c
Normal file
1732
contrib/gcc/cfgexpand.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Hooks for cfg representation specific functions.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sebastian Pop <s.pop@laposte.net>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,8 +16,8 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
@ -26,12 +26,12 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "tree.h"
|
||||
#include "rtl.h"
|
||||
#include "basic-block.h"
|
||||
|
||||
extern struct cfg_hooks rtl_cfg_hooks;
|
||||
extern struct cfg_hooks cfg_layout_rtl_cfg_hooks;
|
||||
#include "tree-flow.h"
|
||||
#include "timevar.h"
|
||||
#include "toplev.h"
|
||||
|
||||
/* A pointer to one of the hooks containers. */
|
||||
struct cfg_hooks *cfg_hooks;
|
||||
static struct cfg_hooks *cfg_hooks;
|
||||
|
||||
/* Initialization of functions specific to the rtl IR. */
|
||||
void
|
||||
@ -46,3 +46,845 @@ cfg_layout_rtl_register_cfg_hooks (void)
|
||||
{
|
||||
cfg_hooks = &cfg_layout_rtl_cfg_hooks;
|
||||
}
|
||||
|
||||
/* Initialization of functions specific to the tree IR. */
|
||||
|
||||
void
|
||||
tree_register_cfg_hooks (void)
|
||||
{
|
||||
cfg_hooks = &tree_cfg_hooks;
|
||||
}
|
||||
|
||||
/* Returns current ir type (rtl = 0, trees = 1). */
|
||||
|
||||
int
|
||||
ir_type (void)
|
||||
{
|
||||
return cfg_hooks == &tree_cfg_hooks ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Verify the CFG consistency.
|
||||
|
||||
Currently it does following: checks edge and basic block list correctness
|
||||
and calls into IL dependent checking then. */
|
||||
|
||||
void
|
||||
verify_flow_info (void)
|
||||
{
|
||||
size_t *edge_checksum;
|
||||
int err = 0;
|
||||
basic_block bb, last_bb_seen;
|
||||
basic_block *last_visited;
|
||||
|
||||
timevar_push (TV_CFG_VERIFY);
|
||||
last_visited = XCNEWVEC (basic_block, last_basic_block);
|
||||
edge_checksum = XCNEWVEC (size_t, last_basic_block);
|
||||
|
||||
/* Check bb chain & numbers. */
|
||||
last_bb_seen = ENTRY_BLOCK_PTR;
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb, NULL, next_bb)
|
||||
{
|
||||
if (bb != EXIT_BLOCK_PTR
|
||||
&& bb != BASIC_BLOCK (bb->index))
|
||||
{
|
||||
error ("bb %d on wrong place", bb->index);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (bb->prev_bb != last_bb_seen)
|
||||
{
|
||||
error ("prev_bb of %d should be %d, not %d",
|
||||
bb->index, last_bb_seen->index, bb->prev_bb->index);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
last_bb_seen = bb;
|
||||
}
|
||||
|
||||
/* Now check the basic blocks (boundaries etc.) */
|
||||
FOR_EACH_BB_REVERSE (bb)
|
||||
{
|
||||
int n_fallthru = 0;
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
if (bb->count < 0)
|
||||
{
|
||||
error ("verify_flow_info: Wrong count of block %i %i",
|
||||
bb->index, (int)bb->count);
|
||||
err = 1;
|
||||
}
|
||||
if (bb->frequency < 0)
|
||||
{
|
||||
error ("verify_flow_info: Wrong frequency of block %i %i",
|
||||
bb->index, bb->frequency);
|
||||
err = 1;
|
||||
}
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
{
|
||||
if (last_visited [e->dest->index] == bb)
|
||||
{
|
||||
error ("verify_flow_info: Duplicate edge %i->%i",
|
||||
e->src->index, e->dest->index);
|
||||
err = 1;
|
||||
}
|
||||
if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
|
||||
{
|
||||
error ("verify_flow_info: Wrong probability of edge %i->%i %i",
|
||||
e->src->index, e->dest->index, e->probability);
|
||||
err = 1;
|
||||
}
|
||||
if (e->count < 0)
|
||||
{
|
||||
error ("verify_flow_info: Wrong count of edge %i->%i %i",
|
||||
e->src->index, e->dest->index, (int)e->count);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
last_visited [e->dest->index] = bb;
|
||||
|
||||
if (e->flags & EDGE_FALLTHRU)
|
||||
n_fallthru++;
|
||||
|
||||
if (e->src != bb)
|
||||
{
|
||||
error ("verify_flow_info: Basic block %d succ edge is corrupted",
|
||||
bb->index);
|
||||
fprintf (stderr, "Predecessor: ");
|
||||
dump_edge_info (stderr, e, 0);
|
||||
fprintf (stderr, "\nSuccessor: ");
|
||||
dump_edge_info (stderr, e, 1);
|
||||
fprintf (stderr, "\n");
|
||||
err = 1;
|
||||
}
|
||||
|
||||
edge_checksum[e->dest->index] += (size_t) e;
|
||||
}
|
||||
if (n_fallthru > 1)
|
||||
{
|
||||
error ("wrong amount of branch edges after unconditional jump %i", bb->index);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
{
|
||||
if (e->dest != bb)
|
||||
{
|
||||
error ("basic block %d pred edge is corrupted", bb->index);
|
||||
fputs ("Predecessor: ", stderr);
|
||||
dump_edge_info (stderr, e, 0);
|
||||
fputs ("\nSuccessor: ", stderr);
|
||||
dump_edge_info (stderr, e, 1);
|
||||
fputc ('\n', stderr);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (ei.index != e->dest_idx)
|
||||
{
|
||||
error ("basic block %d pred edge is corrupted", bb->index);
|
||||
error ("its dest_idx should be %d, not %d",
|
||||
ei.index, e->dest_idx);
|
||||
fputs ("Predecessor: ", stderr);
|
||||
dump_edge_info (stderr, e, 0);
|
||||
fputs ("\nSuccessor: ", stderr);
|
||||
dump_edge_info (stderr, e, 1);
|
||||
fputc ('\n', stderr);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
edge_checksum[e->dest->index] -= (size_t) e;
|
||||
}
|
||||
}
|
||||
|
||||
/* Complete edge checksumming for ENTRY and EXIT. */
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs)
|
||||
edge_checksum[e->dest->index] += (size_t) e;
|
||||
|
||||
FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
|
||||
edge_checksum[e->dest->index] -= (size_t) e;
|
||||
}
|
||||
|
||||
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
|
||||
if (edge_checksum[bb->index])
|
||||
{
|
||||
error ("basic block %i edge lists are corrupted", bb->index);
|
||||
err = 1;
|
||||
}
|
||||
|
||||
last_bb_seen = ENTRY_BLOCK_PTR;
|
||||
|
||||
/* Clean up. */
|
||||
free (last_visited);
|
||||
free (edge_checksum);
|
||||
|
||||
if (cfg_hooks->verify_flow_info)
|
||||
err |= cfg_hooks->verify_flow_info ();
|
||||
if (err)
|
||||
internal_error ("verify_flow_info failed");
|
||||
timevar_pop (TV_CFG_VERIFY);
|
||||
}
|
||||
|
||||
/* Print out one basic block. This function takes care of the purely
|
||||
graph related information. The cfg hook for the active representation
|
||||
should dump representation-specific information. */
|
||||
|
||||
void
|
||||
dump_bb (basic_block bb, FILE *outf, int indent)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
char *s_indent;
|
||||
|
||||
s_indent = alloca ((size_t) indent + 1);
|
||||
memset (s_indent, ' ', (size_t) indent);
|
||||
s_indent[indent] = '\0';
|
||||
|
||||
fprintf (outf, ";;%s basic block %d, loop depth %d, count ",
|
||||
s_indent, bb->index, bb->loop_depth);
|
||||
fprintf (outf, HOST_WIDEST_INT_PRINT_DEC, (HOST_WIDEST_INT) bb->count);
|
||||
putc ('\n', outf);
|
||||
|
||||
fprintf (outf, ";;%s prev block ", s_indent);
|
||||
if (bb->prev_bb)
|
||||
fprintf (outf, "%d, ", bb->prev_bb->index);
|
||||
else
|
||||
fprintf (outf, "(nil), ");
|
||||
fprintf (outf, "next block ");
|
||||
if (bb->next_bb)
|
||||
fprintf (outf, "%d", bb->next_bb->index);
|
||||
else
|
||||
fprintf (outf, "(nil)");
|
||||
putc ('\n', outf);
|
||||
|
||||
fprintf (outf, ";;%s pred: ", s_indent);
|
||||
FOR_EACH_EDGE (e, ei, bb->preds)
|
||||
dump_edge_info (outf, e, 0);
|
||||
putc ('\n', outf);
|
||||
|
||||
fprintf (outf, ";;%s succ: ", s_indent);
|
||||
FOR_EACH_EDGE (e, ei, bb->succs)
|
||||
dump_edge_info (outf, e, 1);
|
||||
putc ('\n', outf);
|
||||
|
||||
if (cfg_hooks->dump_bb)
|
||||
cfg_hooks->dump_bb (bb, outf, indent);
|
||||
}
|
||||
|
||||
/* Redirect edge E to the given basic block DEST and update underlying program
|
||||
representation. Returns edge representing redirected branch (that may not
|
||||
be equivalent to E in the case of duplicate edges being removed) or NULL
|
||||
if edge is not easily redirectable for whatever reason. */
|
||||
|
||||
edge
|
||||
redirect_edge_and_branch (edge e, basic_block dest)
|
||||
{
|
||||
edge ret;
|
||||
|
||||
if (!cfg_hooks->redirect_edge_and_branch)
|
||||
internal_error ("%s does not support redirect_edge_and_branch",
|
||||
cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->redirect_edge_and_branch (e, dest);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Redirect the edge E to basic block DEST even if it requires creating
|
||||
of a new basic block; then it returns the newly created basic block.
|
||||
Aborts when redirection is impossible. */
|
||||
|
||||
basic_block
|
||||
redirect_edge_and_branch_force (edge e, basic_block dest)
|
||||
{
|
||||
basic_block ret;
|
||||
|
||||
if (!cfg_hooks->redirect_edge_and_branch_force)
|
||||
internal_error ("%s does not support redirect_edge_and_branch_force",
|
||||
cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->redirect_edge_and_branch_force (e, dest);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Splits basic block BB after the specified instruction I (but at least after
|
||||
the labels). If I is NULL, splits just after labels. The newly created edge
|
||||
is returned. The new basic block is created just after the old one. */
|
||||
|
||||
edge
|
||||
split_block (basic_block bb, void *i)
|
||||
{
|
||||
basic_block new_bb;
|
||||
|
||||
if (!cfg_hooks->split_block)
|
||||
internal_error ("%s does not support split_block", cfg_hooks->name);
|
||||
|
||||
new_bb = cfg_hooks->split_block (bb, i);
|
||||
if (!new_bb)
|
||||
return NULL;
|
||||
|
||||
new_bb->count = bb->count;
|
||||
new_bb->frequency = bb->frequency;
|
||||
new_bb->loop_depth = bb->loop_depth;
|
||||
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
{
|
||||
redirect_immediate_dominators (CDI_DOMINATORS, bb, new_bb);
|
||||
set_immediate_dominator (CDI_DOMINATORS, new_bb, bb);
|
||||
}
|
||||
|
||||
return make_single_succ_edge (bb, new_bb, EDGE_FALLTHRU);
|
||||
}
|
||||
|
||||
/* Splits block BB just after labels. The newly created edge is returned. */
|
||||
|
||||
edge
|
||||
split_block_after_labels (basic_block bb)
|
||||
{
|
||||
return split_block (bb, NULL);
|
||||
}
|
||||
|
||||
/* Moves block BB immediately after block AFTER. Returns false if the
|
||||
movement was impossible. */
|
||||
|
||||
bool
|
||||
move_block_after (basic_block bb, basic_block after)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (!cfg_hooks->move_block_after)
|
||||
internal_error ("%s does not support move_block_after", cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->move_block_after (bb, after);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Deletes the basic block BB. */
|
||||
|
||||
void
|
||||
delete_basic_block (basic_block bb)
|
||||
{
|
||||
if (!cfg_hooks->delete_basic_block)
|
||||
internal_error ("%s does not support delete_basic_block", cfg_hooks->name);
|
||||
|
||||
cfg_hooks->delete_basic_block (bb);
|
||||
|
||||
/* Remove the edges into and out of this block. Note that there may
|
||||
indeed be edges in, if we are removing an unreachable loop. */
|
||||
while (EDGE_COUNT (bb->preds) != 0)
|
||||
remove_edge (EDGE_PRED (bb, 0));
|
||||
while (EDGE_COUNT (bb->succs) != 0)
|
||||
remove_edge (EDGE_SUCC (bb, 0));
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS])
|
||||
delete_from_dominance_info (CDI_DOMINATORS, bb);
|
||||
if (dom_computed[CDI_POST_DOMINATORS])
|
||||
delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
|
||||
|
||||
/* Remove the basic block from the array. */
|
||||
expunge_block (bb);
|
||||
}
|
||||
|
||||
/* Splits edge E and returns the newly created basic block. */
|
||||
|
||||
basic_block
|
||||
split_edge (edge e)
|
||||
{
|
||||
basic_block ret;
|
||||
gcov_type count = e->count;
|
||||
int freq = EDGE_FREQUENCY (e);
|
||||
edge f;
|
||||
bool irr = (e->flags & EDGE_IRREDUCIBLE_LOOP) != 0;
|
||||
|
||||
if (!cfg_hooks->split_edge)
|
||||
internal_error ("%s does not support split_edge", cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->split_edge (e);
|
||||
ret->count = count;
|
||||
ret->frequency = freq;
|
||||
single_succ_edge (ret)->probability = REG_BR_PROB_BASE;
|
||||
single_succ_edge (ret)->count = count;
|
||||
|
||||
if (irr)
|
||||
{
|
||||
ret->flags |= BB_IRREDUCIBLE_LOOP;
|
||||
single_pred_edge (ret)->flags |= EDGE_IRREDUCIBLE_LOOP;
|
||||
single_succ_edge (ret)->flags |= EDGE_IRREDUCIBLE_LOOP;
|
||||
}
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS])
|
||||
set_immediate_dominator (CDI_DOMINATORS, ret, single_pred (ret));
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS] >= DOM_NO_FAST_QUERY)
|
||||
{
|
||||
/* There are two cases:
|
||||
|
||||
If the immediate dominator of e->dest is not e->src, it
|
||||
remains unchanged.
|
||||
|
||||
If immediate dominator of e->dest is e->src, it may become
|
||||
ret, provided that all other predecessors of e->dest are
|
||||
dominated by e->dest. */
|
||||
|
||||
if (get_immediate_dominator (CDI_DOMINATORS, single_succ (ret))
|
||||
== single_pred (ret))
|
||||
{
|
||||
edge_iterator ei;
|
||||
FOR_EACH_EDGE (f, ei, single_succ (ret)->preds)
|
||||
{
|
||||
if (f == single_succ_edge (ret))
|
||||
continue;
|
||||
|
||||
if (!dominated_by_p (CDI_DOMINATORS, f->src,
|
||||
single_succ (ret)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (!f)
|
||||
set_immediate_dominator (CDI_DOMINATORS, single_succ (ret), ret);
|
||||
}
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Creates a new basic block just after the basic block AFTER.
|
||||
HEAD and END are the first and the last statement belonging
|
||||
to the block. If both are NULL, an empty block is created. */
|
||||
|
||||
basic_block
|
||||
create_basic_block (void *head, void *end, basic_block after)
|
||||
{
|
||||
basic_block ret;
|
||||
|
||||
if (!cfg_hooks->create_basic_block)
|
||||
internal_error ("%s does not support create_basic_block", cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->create_basic_block (head, end, after);
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS])
|
||||
add_to_dominance_info (CDI_DOMINATORS, ret);
|
||||
if (dom_computed[CDI_POST_DOMINATORS])
|
||||
add_to_dominance_info (CDI_POST_DOMINATORS, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Creates an empty basic block just after basic block AFTER. */
|
||||
|
||||
basic_block
|
||||
create_empty_bb (basic_block after)
|
||||
{
|
||||
return create_basic_block (NULL, NULL, after);
|
||||
}
|
||||
|
||||
/* Checks whether we may merge blocks BB1 and BB2. */
|
||||
|
||||
bool
|
||||
can_merge_blocks_p (basic_block bb1, basic_block bb2)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
if (!cfg_hooks->can_merge_blocks_p)
|
||||
internal_error ("%s does not support can_merge_blocks_p", cfg_hooks->name);
|
||||
|
||||
ret = cfg_hooks->can_merge_blocks_p (bb1, bb2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
predict_edge (edge e, enum br_predictor predictor, int probability)
|
||||
{
|
||||
if (!cfg_hooks->predict_edge)
|
||||
internal_error ("%s does not support predict_edge", cfg_hooks->name);
|
||||
|
||||
cfg_hooks->predict_edge (e, predictor, probability);
|
||||
}
|
||||
|
||||
bool
|
||||
predicted_by_p (basic_block bb, enum br_predictor predictor)
|
||||
{
|
||||
if (!cfg_hooks->predict_edge)
|
||||
internal_error ("%s does not support predicted_by_p", cfg_hooks->name);
|
||||
|
||||
return cfg_hooks->predicted_by_p (bb, predictor);
|
||||
}
|
||||
|
||||
/* Merges basic block B into basic block A. */
|
||||
|
||||
void
|
||||
merge_blocks (basic_block a, basic_block b)
|
||||
{
|
||||
edge e;
|
||||
edge_iterator ei;
|
||||
|
||||
if (!cfg_hooks->merge_blocks)
|
||||
internal_error ("%s does not support merge_blocks", cfg_hooks->name);
|
||||
|
||||
cfg_hooks->merge_blocks (a, b);
|
||||
|
||||
/* Normally there should only be one successor of A and that is B, but
|
||||
partway though the merge of blocks for conditional_execution we'll
|
||||
be merging a TEST block with THEN and ELSE successors. Free the
|
||||
whole lot of them and hope the caller knows what they're doing. */
|
||||
|
||||
while (EDGE_COUNT (a->succs) != 0)
|
||||
remove_edge (EDGE_SUCC (a, 0));
|
||||
|
||||
/* Adjust the edges out of B for the new owner. */
|
||||
FOR_EACH_EDGE (e, ei, b->succs)
|
||||
e->src = a;
|
||||
a->succs = b->succs;
|
||||
a->flags |= b->flags;
|
||||
|
||||
/* B hasn't quite yet ceased to exist. Attempt to prevent mishap. */
|
||||
b->preds = b->succs = NULL;
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS])
|
||||
redirect_immediate_dominators (CDI_DOMINATORS, b, a);
|
||||
|
||||
if (dom_computed[CDI_DOMINATORS])
|
||||
delete_from_dominance_info (CDI_DOMINATORS, b);
|
||||
if (dom_computed[CDI_POST_DOMINATORS])
|
||||
delete_from_dominance_info (CDI_POST_DOMINATORS, b);
|
||||
|
||||
expunge_block (b);
|
||||
}
|
||||
|
||||
/* Split BB into entry part and the rest (the rest is the newly created block).
|
||||
Redirect those edges for that REDIRECT_EDGE_P returns true to the entry
|
||||
part. Returns the edge connecting the entry part to the rest. */
|
||||
|
||||
edge
|
||||
make_forwarder_block (basic_block bb, bool (*redirect_edge_p) (edge),
|
||||
void (*new_bb_cbk) (basic_block))
|
||||
{
|
||||
edge e, fallthru;
|
||||
edge_iterator ei;
|
||||
basic_block dummy, jump;
|
||||
|
||||
if (!cfg_hooks->make_forwarder_block)
|
||||
internal_error ("%s does not support make_forwarder_block",
|
||||
cfg_hooks->name);
|
||||
|
||||
fallthru = split_block_after_labels (bb);
|
||||
dummy = fallthru->src;
|
||||
bb = fallthru->dest;
|
||||
|
||||
/* Redirect back edges we want to keep. */
|
||||
for (ei = ei_start (dummy->preds); (e = ei_safe_edge (ei)); )
|
||||
{
|
||||
if (redirect_edge_p (e))
|
||||
{
|
||||
ei_next (&ei);
|
||||
continue;
|
||||
}
|
||||
|
||||
dummy->frequency -= EDGE_FREQUENCY (e);
|
||||
dummy->count -= e->count;
|
||||
if (dummy->frequency < 0)
|
||||
dummy->frequency = 0;
|
||||
if (dummy->count < 0)
|
||||
dummy->count = 0;
|
||||
fallthru->count -= e->count;
|
||||
if (fallthru->count < 0)
|
||||
fallthru->count = 0;
|
||||
|
||||
jump = redirect_edge_and_branch_force (e, bb);
|
||||
if (jump)
|
||||
new_bb_cbk (jump);
|
||||
}
|
||||
|
||||
if (dom_info_available_p (CDI_DOMINATORS))
|
||||
{
|
||||
basic_block doms_to_fix[2];
|
||||
|
||||
doms_to_fix[0] = dummy;
|
||||
doms_to_fix[1] = bb;
|
||||
iterate_fix_dominators (CDI_DOMINATORS, doms_to_fix, 2);
|
||||
}
|
||||
|
||||
cfg_hooks->make_forwarder_block (fallthru);
|
||||
|
||||
return fallthru;
|
||||
}
|
||||
|
||||
void
|
||||
tidy_fallthru_edge (edge e)
|
||||
{
|
||||
if (cfg_hooks->tidy_fallthru_edge)
|
||||
cfg_hooks->tidy_fallthru_edge (e);
|
||||
}
|
||||
|
||||
/* Fix up edges that now fall through, or rather should now fall through
|
||||
but previously required a jump around now deleted blocks. Simplify
|
||||
the search by only examining blocks numerically adjacent, since this
|
||||
is how find_basic_blocks created them. */
|
||||
|
||||
void
|
||||
tidy_fallthru_edges (void)
|
||||
{
|
||||
basic_block b, c;
|
||||
|
||||
if (!cfg_hooks->tidy_fallthru_edge)
|
||||
return;
|
||||
|
||||
if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
|
||||
return;
|
||||
|
||||
FOR_BB_BETWEEN (b, ENTRY_BLOCK_PTR->next_bb, EXIT_BLOCK_PTR->prev_bb, next_bb)
|
||||
{
|
||||
edge s;
|
||||
|
||||
c = b->next_bb;
|
||||
|
||||
/* We care about simple conditional or unconditional jumps with
|
||||
a single successor.
|
||||
|
||||
If we had a conditional branch to the next instruction when
|
||||
find_basic_blocks was called, then there will only be one
|
||||
out edge for the block which ended with the conditional
|
||||
branch (since we do not create duplicate edges).
|
||||
|
||||
Furthermore, the edge will be marked as a fallthru because we
|
||||
merge the flags for the duplicate edges. So we do not want to
|
||||
check that the edge is not a FALLTHRU edge. */
|
||||
|
||||
if (single_succ_p (b))
|
||||
{
|
||||
s = single_succ_edge (b);
|
||||
if (! (s->flags & EDGE_COMPLEX)
|
||||
&& s->dest == c
|
||||
&& !find_reg_note (BB_END (b), REG_CROSSING_JUMP, NULL_RTX))
|
||||
tidy_fallthru_edge (s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns true if we can duplicate basic block BB. */
|
||||
|
||||
bool
|
||||
can_duplicate_block_p (basic_block bb)
|
||||
{
|
||||
edge e;
|
||||
|
||||
if (!cfg_hooks->can_duplicate_block_p)
|
||||
internal_error ("%s does not support can_duplicate_block_p",
|
||||
cfg_hooks->name);
|
||||
|
||||
if (bb == EXIT_BLOCK_PTR || bb == ENTRY_BLOCK_PTR)
|
||||
return false;
|
||||
|
||||
/* Duplicating fallthru block to exit would require adding a jump
|
||||
and splitting the real last BB. */
|
||||
e = find_edge (bb, EXIT_BLOCK_PTR);
|
||||
if (e && (e->flags & EDGE_FALLTHRU))
|
||||
return false;
|
||||
|
||||
return cfg_hooks->can_duplicate_block_p (bb);
|
||||
}
|
||||
|
||||
/* Duplicates basic block BB and redirects edge E to it. Returns the
|
||||
new basic block. The new basic block is placed after the basic block
|
||||
AFTER. */
|
||||
|
||||
basic_block
|
||||
duplicate_block (basic_block bb, edge e, basic_block after)
|
||||
{
|
||||
edge s, n;
|
||||
basic_block new_bb;
|
||||
gcov_type new_count = e ? e->count : 0;
|
||||
edge_iterator ei;
|
||||
|
||||
if (!cfg_hooks->duplicate_block)
|
||||
internal_error ("%s does not support duplicate_block",
|
||||
cfg_hooks->name);
|
||||
|
||||
if (bb->count < new_count)
|
||||
new_count = bb->count;
|
||||
|
||||
#ifdef ENABLE_CHECKING
|
||||
gcc_assert (can_duplicate_block_p (bb));
|
||||
#endif
|
||||
|
||||
new_bb = cfg_hooks->duplicate_block (bb);
|
||||
if (after)
|
||||
move_block_after (new_bb, after);
|
||||
|
||||
new_bb->loop_depth = bb->loop_depth;
|
||||
new_bb->flags = bb->flags;
|
||||
FOR_EACH_EDGE (s, ei, bb->succs)
|
||||
{
|
||||
/* Since we are creating edges from a new block to successors
|
||||
of another block (which therefore are known to be disjoint), there
|
||||
is no need to actually check for duplicated edges. */
|
||||
n = unchecked_make_edge (new_bb, s->dest, s->flags);
|
||||
n->probability = s->probability;
|
||||
if (e && bb->count)
|
||||
{
|
||||
/* Take care for overflows! */
|
||||
n->count = s->count * (new_count * 10000 / bb->count) / 10000;
|
||||
s->count -= n->count;
|
||||
}
|
||||
else
|
||||
n->count = s->count;
|
||||
n->aux = s->aux;
|
||||
}
|
||||
|
||||
if (e)
|
||||
{
|
||||
new_bb->count = new_count;
|
||||
bb->count -= new_count;
|
||||
|
||||
new_bb->frequency = EDGE_FREQUENCY (e);
|
||||
bb->frequency -= EDGE_FREQUENCY (e);
|
||||
|
||||
redirect_edge_and_branch_force (e, new_bb);
|
||||
|
||||
if (bb->count < 0)
|
||||
bb->count = 0;
|
||||
if (bb->frequency < 0)
|
||||
bb->frequency = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_bb->count = bb->count;
|
||||
new_bb->frequency = bb->frequency;
|
||||
}
|
||||
|
||||
set_bb_original (new_bb, bb);
|
||||
set_bb_copy (bb, new_bb);
|
||||
|
||||
return new_bb;
|
||||
}
|
||||
|
||||
/* Return 1 if BB ends with a call, possibly followed by some
|
||||
instructions that must stay with the call, 0 otherwise. */
|
||||
|
||||
bool
|
||||
block_ends_with_call_p (basic_block bb)
|
||||
{
|
||||
if (!cfg_hooks->block_ends_with_call_p)
|
||||
internal_error ("%s does not support block_ends_with_call_p", cfg_hooks->name);
|
||||
|
||||
return (cfg_hooks->block_ends_with_call_p) (bb);
|
||||
}
|
||||
|
||||
/* Return 1 if BB ends with a conditional branch, 0 otherwise. */
|
||||
|
||||
bool
|
||||
block_ends_with_condjump_p (basic_block bb)
|
||||
{
|
||||
if (!cfg_hooks->block_ends_with_condjump_p)
|
||||
internal_error ("%s does not support block_ends_with_condjump_p",
|
||||
cfg_hooks->name);
|
||||
|
||||
return (cfg_hooks->block_ends_with_condjump_p) (bb);
|
||||
}
|
||||
|
||||
/* Add fake edges to the function exit for any non constant and non noreturn
|
||||
calls, volatile inline assembly in the bitmap of blocks specified by
|
||||
BLOCKS or to the whole CFG if BLOCKS is zero. Return the number of blocks
|
||||
that were split.
|
||||
|
||||
The goal is to expose cases in which entering a basic block does not imply
|
||||
that all subsequent instructions must be executed. */
|
||||
|
||||
int
|
||||
flow_call_edges_add (sbitmap blocks)
|
||||
{
|
||||
if (!cfg_hooks->flow_call_edges_add)
|
||||
internal_error ("%s does not support flow_call_edges_add",
|
||||
cfg_hooks->name);
|
||||
|
||||
return (cfg_hooks->flow_call_edges_add) (blocks);
|
||||
}
|
||||
|
||||
/* This function is called immediately after edge E is added to the
|
||||
edge vector E->dest->preds. */
|
||||
|
||||
void
|
||||
execute_on_growing_pred (edge e)
|
||||
{
|
||||
if (cfg_hooks->execute_on_growing_pred)
|
||||
cfg_hooks->execute_on_growing_pred (e);
|
||||
}
|
||||
|
||||
/* This function is called immediately before edge E is removed from
|
||||
the edge vector E->dest->preds. */
|
||||
|
||||
void
|
||||
execute_on_shrinking_pred (edge e)
|
||||
{
|
||||
if (cfg_hooks->execute_on_shrinking_pred)
|
||||
cfg_hooks->execute_on_shrinking_pred (e);
|
||||
}
|
||||
|
||||
/* This is used inside loop versioning when we want to insert
|
||||
stmts/insns on the edges, which have a different behavior
|
||||
in tree's and in RTL, so we made a CFG hook. */
|
||||
void
|
||||
lv_flush_pending_stmts (edge e)
|
||||
{
|
||||
if (cfg_hooks->flush_pending_stmts)
|
||||
cfg_hooks->flush_pending_stmts (e);
|
||||
}
|
||||
|
||||
/* Loop versioning uses the duplicate_loop_to_header_edge to create
|
||||
a new version of the loop basic-blocks, the parameters here are
|
||||
exactly the same as in duplicate_loop_to_header_edge or
|
||||
tree_duplicate_loop_to_header_edge; while in tree-ssa there is
|
||||
additional work to maintain ssa information that's why there is
|
||||
a need to call the tree_duplicate_loop_to_header_edge rather
|
||||
than duplicate_loop_to_header_edge when we are in tree mode. */
|
||||
bool
|
||||
cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge e,
|
||||
struct loops *loops, unsigned int ndupl,
|
||||
sbitmap wont_exit, edge orig,
|
||||
edge *to_remove,
|
||||
unsigned int *n_to_remove, int flags)
|
||||
{
|
||||
gcc_assert (cfg_hooks->cfg_hook_duplicate_loop_to_header_edge);
|
||||
return cfg_hooks->cfg_hook_duplicate_loop_to_header_edge (loop, e, loops,
|
||||
ndupl, wont_exit,
|
||||
orig, to_remove,
|
||||
n_to_remove, flags);
|
||||
}
|
||||
|
||||
/* Conditional jumps are represented differently in trees and RTL,
|
||||
this hook takes a basic block that is known to have a cond jump
|
||||
at its end and extracts the taken and not taken eges out of it
|
||||
and store it in E1 and E2 respectively. */
|
||||
void
|
||||
extract_cond_bb_edges (basic_block b, edge *e1, edge *e2)
|
||||
{
|
||||
gcc_assert (cfg_hooks->extract_cond_bb_edges);
|
||||
cfg_hooks->extract_cond_bb_edges (b, e1, e2);
|
||||
}
|
||||
|
||||
/* Responsible for updating the ssa info (PHI nodes) on the
|
||||
new condition basic block that guards the versioned loop. */
|
||||
void
|
||||
lv_adjust_loop_header_phi (basic_block first, basic_block second,
|
||||
basic_block new, edge e)
|
||||
{
|
||||
if (cfg_hooks->lv_adjust_loop_header_phi)
|
||||
cfg_hooks->lv_adjust_loop_header_phi (first, second, new, e);
|
||||
}
|
||||
|
||||
/* Conditions in trees and RTL are different so we need
|
||||
a different handling when we add the condition to the
|
||||
versioning code. */
|
||||
void
|
||||
lv_add_condition_to_bb (basic_block first, basic_block second,
|
||||
basic_block new, void *cond)
|
||||
{
|
||||
gcc_assert (cfg_hooks->lv_add_condition_to_bb);
|
||||
cfg_hooks->lv_add_condition_to_bb (first, second, new, cond);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Hooks for cfg representation specific functions.
|
||||
Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Sebastian Pop <s.pop@laposte.net>
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,18 +16,20 @@ GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_CFGHOOKS_H
|
||||
#define GCC_CFGHOOKS_H
|
||||
|
||||
struct cfg_hooks
|
||||
{
|
||||
/* Debugging. Do not use macros to hook these so they can be called from
|
||||
debugger! */
|
||||
int (*cfgh_verify_flow_info) (void);
|
||||
void (*dump_bb) (basic_block, FILE *);
|
||||
/* Name of the corresponding ir. */
|
||||
const char *name;
|
||||
|
||||
/* Debugging. */
|
||||
int (*verify_flow_info) (void);
|
||||
void (*dump_bb) (basic_block, FILE *, int);
|
||||
|
||||
/* Basic CFG manipulation. */
|
||||
|
||||
@ -35,20 +37,25 @@ struct cfg_hooks
|
||||
basic_block (*create_basic_block) (void *head, void *end, basic_block after);
|
||||
|
||||
/* Redirect edge E to the given basic block B and update underlying program
|
||||
representation. Returns false when edge is not easily redirectable for
|
||||
whatever reason. */
|
||||
bool (*redirect_edge_and_branch) (edge e, basic_block b);
|
||||
representation. Returns edge representing redirected branch (that may not
|
||||
be equivalent to E in the case of duplicate edges being removed) or NULL
|
||||
if edge is not easily redirectable for whatever reason. */
|
||||
edge (*redirect_edge_and_branch) (edge e, basic_block b);
|
||||
|
||||
/* Same as the above but allows redirecting of fallthru edges. In that case
|
||||
newly created forwarder basic block is returned. It aborts when called
|
||||
on abnormal edge. */
|
||||
newly created forwarder basic block is returned. The edge must
|
||||
not be abnormal. */
|
||||
basic_block (*redirect_edge_and_branch_force) (edge, basic_block);
|
||||
|
||||
/* Remove given basic block and all edges possibly pointing into it. */
|
||||
void (*delete_block) (basic_block);
|
||||
/* Remove statements corresponding to a given basic block. */
|
||||
void (*delete_basic_block) (basic_block);
|
||||
|
||||
/* Split basic block B after specified instruction I. */
|
||||
edge (*split_block) (basic_block b, void * i);
|
||||
/* Creates a new basic block just after basic block B by splitting
|
||||
everything after specified instruction I. */
|
||||
basic_block (*split_block) (basic_block b, void * i);
|
||||
|
||||
/* Move block B immediately after block A. */
|
||||
bool (*move_block_after) (basic_block b, basic_block a);
|
||||
|
||||
/* Return true when blocks A and B can be merged into single basic block. */
|
||||
bool (*can_merge_blocks_p) (basic_block a, basic_block b);
|
||||
@ -56,28 +63,130 @@ struct cfg_hooks
|
||||
/* Merge blocks A and B. */
|
||||
void (*merge_blocks) (basic_block a, basic_block b);
|
||||
|
||||
/* Predict edge E using PREDICTOR to given PROBABILITY. */
|
||||
void (*predict_edge) (edge e, enum br_predictor predictor, int probability);
|
||||
|
||||
/* Return true if the one of outgoing edges is already predicted by
|
||||
PREDICTOR. */
|
||||
bool (*predicted_by_p) (basic_block bb, enum br_predictor predictor);
|
||||
|
||||
/* Return true when block A can be duplicated. */
|
||||
bool (*can_duplicate_block_p) (basic_block a);
|
||||
|
||||
/* Duplicate block A. */
|
||||
basic_block (*duplicate_block) (basic_block a);
|
||||
|
||||
/* Higher level functions representable by primitive operations above if
|
||||
we didn't have some oddities in RTL and Tree representations. */
|
||||
basic_block (*cfgh_split_edge) (edge);
|
||||
basic_block (*split_edge) (edge);
|
||||
void (*make_forwarder_block) (edge);
|
||||
|
||||
/* Tries to make the edge fallthru. */
|
||||
void (*tidy_fallthru_edge) (edge);
|
||||
|
||||
/* Say whether a block ends with a call, possibly followed by some
|
||||
other code that must stay with the call. */
|
||||
bool (*block_ends_with_call_p) (basic_block);
|
||||
|
||||
/* Say whether a block ends with a conditional branch. Switches
|
||||
and unconditional branches do not qualify. */
|
||||
bool (*block_ends_with_condjump_p) (basic_block);
|
||||
|
||||
/* Add fake edges to the function exit for any non constant and non noreturn
|
||||
calls, volatile inline assembly in the bitmap of blocks specified by
|
||||
BLOCKS or to the whole CFG if BLOCKS is zero. Return the number of blocks
|
||||
that were split.
|
||||
|
||||
The goal is to expose cases in which entering a basic block does not imply
|
||||
that all subsequent instructions must be executed. */
|
||||
int (*flow_call_edges_add) (sbitmap);
|
||||
|
||||
/* This function is called immediately after edge E is added to the
|
||||
edge vector E->dest->preds. */
|
||||
void (*execute_on_growing_pred) (edge);
|
||||
|
||||
/* This function is called immediately before edge E is removed from
|
||||
the edge vector E->dest->preds. */
|
||||
void (*execute_on_shrinking_pred) (edge);
|
||||
|
||||
/* A hook for duplicating loop in CFG, currently this is used
|
||||
in loop versioning. */
|
||||
bool (*cfg_hook_duplicate_loop_to_header_edge) (struct loop *loop, edge e,
|
||||
struct loops *loops,
|
||||
unsigned int ndupl,
|
||||
sbitmap wont_exit,
|
||||
edge orig, edge *to_remove,
|
||||
unsigned int *n_to_remove,
|
||||
int flags);
|
||||
|
||||
/* Add condition to new basic block and update CFG used in loop
|
||||
versioning. */
|
||||
void (*lv_add_condition_to_bb) (basic_block, basic_block, basic_block,
|
||||
void *);
|
||||
/* Update the PHI nodes in case of loop versioning. */
|
||||
void (*lv_adjust_loop_header_phi) (basic_block, basic_block,
|
||||
basic_block, edge);
|
||||
|
||||
/* Given a condition BB extract the true/false taken/not taken edges
|
||||
(depending if we are on tree's or RTL). */
|
||||
void (*extract_cond_bb_edges) (basic_block, edge *, edge *);
|
||||
|
||||
|
||||
/* Add PHI arguments queued in PENDINT_STMT list on edge E to edge
|
||||
E->dest (only in tree-ssa loop versioning. */
|
||||
void (*flush_pending_stmts) (edge);
|
||||
};
|
||||
|
||||
#define redirect_edge_and_branch(e,b) cfg_hooks->redirect_edge_and_branch (e,b)
|
||||
#define redirect_edge_and_branch_force(e,b) cfg_hooks->redirect_edge_and_branch_force (e,b)
|
||||
#define split_block(e,i) cfg_hooks->split_block (e,i)
|
||||
#define delete_block(b) cfg_hooks->delete_block (b)
|
||||
#define split_edge(e) cfg_hooks->cfgh_split_edge (e)
|
||||
#define create_basic_block(h,e,a) cfg_hooks->create_basic_block (h,e,a)
|
||||
#define can_merge_blocks_p(a,b) cfg_hooks->can_merge_blocks_p (a,b)
|
||||
#define merge_blocks(a,b) cfg_hooks->merge_blocks (a,b)
|
||||
extern void verify_flow_info (void);
|
||||
extern void dump_bb (basic_block, FILE *, int);
|
||||
extern edge redirect_edge_and_branch (edge, basic_block);
|
||||
extern basic_block redirect_edge_and_branch_force (edge, basic_block);
|
||||
extern edge split_block (basic_block, void *);
|
||||
extern edge split_block_after_labels (basic_block);
|
||||
extern bool move_block_after (basic_block, basic_block);
|
||||
extern void delete_basic_block (basic_block);
|
||||
extern basic_block split_edge (edge);
|
||||
extern basic_block create_basic_block (void *, void *, basic_block);
|
||||
extern basic_block create_empty_bb (basic_block);
|
||||
extern bool can_merge_blocks_p (basic_block, basic_block);
|
||||
extern void merge_blocks (basic_block, basic_block);
|
||||
extern edge make_forwarder_block (basic_block, bool (*)(edge),
|
||||
void (*) (basic_block));
|
||||
extern void tidy_fallthru_edge (edge);
|
||||
extern void tidy_fallthru_edges (void);
|
||||
extern void predict_edge (edge e, enum br_predictor predictor, int probability);
|
||||
extern bool predicted_by_p (basic_block bb, enum br_predictor predictor);
|
||||
extern bool can_duplicate_block_p (basic_block);
|
||||
extern basic_block duplicate_block (basic_block, edge, basic_block);
|
||||
extern bool block_ends_with_call_p (basic_block bb);
|
||||
extern bool block_ends_with_condjump_p (basic_block bb);
|
||||
extern int flow_call_edges_add (sbitmap);
|
||||
extern void execute_on_growing_pred (edge);
|
||||
extern void execute_on_shrinking_pred (edge);
|
||||
extern bool cfg_hook_duplicate_loop_to_header_edge (struct loop *loop, edge,
|
||||
struct loops *loops,
|
||||
unsigned int ndupl,
|
||||
sbitmap wont_exit,
|
||||
edge orig, edge *to_remove,
|
||||
unsigned int *n_to_remove,
|
||||
int flags);
|
||||
|
||||
extern void lv_flush_pending_stmts (edge);
|
||||
extern void extract_cond_bb_edges (basic_block, edge *, edge*);
|
||||
extern void lv_adjust_loop_header_phi (basic_block, basic_block, basic_block,
|
||||
edge);
|
||||
extern void lv_add_condition_to_bb (basic_block, basic_block, basic_block,
|
||||
void *);
|
||||
|
||||
/* Hooks containers. */
|
||||
extern struct cfg_hooks tree_cfg_hooks;
|
||||
extern struct cfg_hooks rtl_cfg_hooks;
|
||||
|
||||
/* A pointer to one of the hooks containers. */
|
||||
extern struct cfg_hooks *cfg_hooks;
|
||||
extern struct cfg_hooks cfg_layout_rtl_cfg_hooks;
|
||||
|
||||
/* Declarations. */
|
||||
extern int ir_type (void);
|
||||
extern void rtl_register_cfg_hooks (void);
|
||||
extern void cfg_layout_rtl_register_cfg_hooks (void);
|
||||
extern void tree_register_cfg_hooks (void);
|
||||
|
||||
#endif /* GCC_CFGHOOKS_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Basic block reordering routines for the GNU compiler.
|
||||
Copyright (C) 2000, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,33 +15,24 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Structure to hold information about the blocks during reordering. */
|
||||
typedef struct reorder_block_def
|
||||
{
|
||||
rtx header;
|
||||
rtx footer;
|
||||
basic_block next;
|
||||
basic_block original;
|
||||
/* Used by loop copying. */
|
||||
basic_block copy;
|
||||
int duplicated;
|
||||
#ifndef GCC_CFGLAYOUT_H
|
||||
#define GCC_CFGLAYOUT_H
|
||||
|
||||
/* These fields are used by bb-reorder pass. */
|
||||
int visited;
|
||||
} *reorder_block_def;
|
||||
#include "basic-block.h"
|
||||
|
||||
extern rtx cfg_layout_function_footer;
|
||||
|
||||
extern void cfg_layout_initialize (unsigned int);
|
||||
extern void cfg_layout_finalize (void);
|
||||
extern bool cfg_layout_can_duplicate_bb_p (basic_block);
|
||||
extern basic_block cfg_layout_duplicate_bb (basic_block, edge);
|
||||
extern void insn_locators_initialize (void);
|
||||
extern unsigned int insn_locators_initialize (void);
|
||||
extern void reemit_insn_block_notes (void);
|
||||
extern bool can_copy_bbs_p (basic_block *, unsigned);
|
||||
extern void copy_bbs (basic_block *, unsigned, basic_block *,
|
||||
edge *, unsigned, edge *, struct loop *);
|
||||
extern void cfg_layout_initialize_rbi (basic_block);
|
||||
edge *, unsigned, edge *, struct loop *,
|
||||
basic_block);
|
||||
extern rtx duplicate_insn_chain (rtx, rtx);
|
||||
|
||||
#endif /* GCC_CFGLAYOUT_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Natural loop functions
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,8 +16,15 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_CFGLOOP_H
|
||||
#define GCC_CFGLOOP_H
|
||||
|
||||
#include "basic-block.h"
|
||||
/* For rtx_code. */
|
||||
#include "rtl.h"
|
||||
|
||||
/* Structure to hold decision about unrolling/peeling. */
|
||||
enum lpt_dec
|
||||
@ -36,27 +43,16 @@ struct lpt_decision
|
||||
unsigned times;
|
||||
};
|
||||
|
||||
/* Description of loop for simple loop unrolling. */
|
||||
struct loop_desc
|
||||
/* The structure describing a bound on number of iterations of a loop. */
|
||||
|
||||
struct nb_iter_bound
|
||||
{
|
||||
int postincr; /* 1 if increment/decrement is done after loop exit condition. */
|
||||
rtx stride; /* Value added to VAR in each iteration. */
|
||||
rtx var; /* Loop control variable. */
|
||||
enum machine_mode inner_mode;
|
||||
/* The mode from that it is extended. */
|
||||
enum rtx_code extend; /* With this extend. */
|
||||
rtx var_alts; /* List of definitions of its initial value. */
|
||||
rtx lim; /* Expression var is compared with. */
|
||||
rtx lim_alts; /* List of definitions of its initial value. */
|
||||
bool const_iter; /* True if it iterates constant number of times. */
|
||||
unsigned HOST_WIDE_INT niter;
|
||||
/* Number of iterations if it is constant. */
|
||||
bool may_be_zero; /* If we cannot determine that the first iteration will pass. */
|
||||
enum rtx_code cond; /* Exit condition. */
|
||||
int neg; /* Set to 1 if loop ends when condition is satisfied. */
|
||||
edge out_edge; /* The exit edge. */
|
||||
edge in_edge; /* And the other one. */
|
||||
int n_branches; /* Number of branches inside the loop. */
|
||||
tree bound; /* The constant expression whose value is an upper
|
||||
bound on the number of executions of ... */
|
||||
tree at_stmt; /* ... this statement during one execution of
|
||||
a loop. */
|
||||
struct nb_iter_bound *next;
|
||||
/* The next bound in a list. */
|
||||
};
|
||||
|
||||
/* Structure to hold information for each natural loop. */
|
||||
@ -71,60 +67,18 @@ struct loop
|
||||
/* Basic block of loop latch. */
|
||||
basic_block latch;
|
||||
|
||||
/* Basic block of loop preheader or NULL if it does not exist. */
|
||||
basic_block pre_header;
|
||||
|
||||
/* For loop unrolling/peeling decision. */
|
||||
struct lpt_decision lpt_decision;
|
||||
|
||||
/* Simple loop description. */
|
||||
int simple;
|
||||
struct loop_desc desc;
|
||||
int has_desc;
|
||||
|
||||
/* Number of loop insns. */
|
||||
unsigned ninsns;
|
||||
|
||||
/* Average number of executed insns per iteration. */
|
||||
unsigned av_ninsns;
|
||||
|
||||
/* Array of edges along the preheader extended basic block trace.
|
||||
The source of the first edge is the root node of preheader
|
||||
extended basic block, if it exists. */
|
||||
edge *pre_header_edges;
|
||||
|
||||
/* Number of edges along the pre_header extended basic block trace. */
|
||||
int num_pre_header_edges;
|
||||
|
||||
/* The first block in the loop. This is not necessarily the same as
|
||||
the loop header. */
|
||||
basic_block first;
|
||||
|
||||
/* The last block in the loop. This is not necessarily the same as
|
||||
the loop latch. */
|
||||
basic_block last;
|
||||
|
||||
/* Bitmap of blocks contained within the loop. */
|
||||
sbitmap nodes;
|
||||
|
||||
/* Number of blocks contained within the loop. */
|
||||
unsigned num_nodes;
|
||||
|
||||
/* Array of edges that enter the loop. */
|
||||
edge *entry_edges;
|
||||
|
||||
/* Number of edges that enter the loop. */
|
||||
int num_entries;
|
||||
|
||||
/* Array of edges that exit the loop. */
|
||||
edge *exit_edges;
|
||||
|
||||
/* Number of edges that exit the loop. */
|
||||
int num_exits;
|
||||
|
||||
/* Bitmap of blocks that dominate all exits of the loop. */
|
||||
sbitmap exits_doms;
|
||||
|
||||
/* The loop nesting depth. */
|
||||
int depth;
|
||||
|
||||
@ -147,55 +101,32 @@ struct loop
|
||||
/* Loop that is copy of this loop. */
|
||||
struct loop *copy;
|
||||
|
||||
/* Nonzero if the loop is invalid (e.g., contains setjmp.). */
|
||||
int invalid;
|
||||
|
||||
/* Auxiliary info specific to a pass. */
|
||||
void *aux;
|
||||
|
||||
/* The following are currently used by loop.c but they are likely to
|
||||
disappear as loop.c is converted to use the CFG. */
|
||||
/* The probable number of times the loop is executed at runtime.
|
||||
This is an INTEGER_CST or an expression containing symbolic
|
||||
names. Don't access this field directly:
|
||||
number_of_iterations_in_loop computes and caches the computed
|
||||
information in this field. */
|
||||
tree nb_iterations;
|
||||
|
||||
/* Nonzero if the loop has a NOTE_INSN_LOOP_VTOP. */
|
||||
rtx vtop;
|
||||
/* An INTEGER_CST estimation of the number of iterations. NULL_TREE
|
||||
if there is no estimation. */
|
||||
tree estimated_nb_iterations;
|
||||
|
||||
/* Nonzero if the loop has a NOTE_INSN_LOOP_CONT.
|
||||
A continue statement will generate a branch to NEXT_INSN (cont). */
|
||||
rtx cont;
|
||||
/* Upper bound on number of iterations of a loop. */
|
||||
struct nb_iter_bound *bounds;
|
||||
|
||||
/* The dominator of cont. */
|
||||
rtx cont_dominator;
|
||||
/* If not NULL, loop has just single exit edge stored here (edges to the
|
||||
EXIT_BLOCK_PTR do not count. */
|
||||
edge single_exit;
|
||||
|
||||
/* The NOTE_INSN_LOOP_BEG. */
|
||||
rtx start;
|
||||
|
||||
/* The NOTE_INSN_LOOP_END. */
|
||||
rtx end;
|
||||
|
||||
/* For a rotated loop that is entered near the bottom,
|
||||
this is the label at the top. Otherwise it is zero. */
|
||||
rtx top;
|
||||
|
||||
/* Place in the loop where control enters. */
|
||||
rtx scan_start;
|
||||
|
||||
/* The position where to sink insns out of the loop. */
|
||||
rtx sink;
|
||||
|
||||
/* List of all LABEL_REFs which refer to code labels outside the
|
||||
loop. Used by routines that need to know all loop exits, such as
|
||||
final_biv_value and final_giv_value.
|
||||
|
||||
This does not include loop exits due to return instructions.
|
||||
This is because all bivs and givs are pseudos, and hence must be
|
||||
dead after a return, so the presence of a return does not affect
|
||||
any of the optimizations that use this info. It is simpler to
|
||||
just not include return instructions on this list. */
|
||||
rtx exit_labels;
|
||||
|
||||
/* The number of LABEL_REFs on exit_labels for this loop and all
|
||||
loops nested inside it. */
|
||||
int exit_count;
|
||||
/* True when the loop does not carry data dependences, and
|
||||
consequently the iterations can be executed in any order. False
|
||||
when the loop carries data dependences, or when the property is
|
||||
not decidable. */
|
||||
bool parallel_p;
|
||||
};
|
||||
|
||||
/* Flags for state of loop structure. */
|
||||
@ -203,25 +134,26 @@ enum
|
||||
{
|
||||
LOOPS_HAVE_PREHEADERS = 1,
|
||||
LOOPS_HAVE_SIMPLE_LATCHES = 2,
|
||||
LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4
|
||||
LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS = 4,
|
||||
LOOPS_HAVE_MARKED_SINGLE_EXITS = 8
|
||||
};
|
||||
|
||||
#define LOOPS_NORMAL (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES \
|
||||
| LOOPS_HAVE_MARKED_IRREDUCIBLE_REGIONS)
|
||||
|
||||
/* Structure to hold CFG information about natural loops within a function. */
|
||||
struct loops
|
||||
{
|
||||
/* Number of natural loops in the function. */
|
||||
unsigned num;
|
||||
|
||||
/* Maximum nested loop level in the function. */
|
||||
unsigned levels;
|
||||
/* State of loops. */
|
||||
int state;
|
||||
|
||||
/* Array of natural loop descriptors (scanning this array in reverse order
|
||||
will find the inner loops before their enclosing outer loops). */
|
||||
struct loop *array;
|
||||
|
||||
/* The above array is unused in new loop infrastructure and is kept only for
|
||||
purposes of the old loop optimizer. Instead we store just pointers to
|
||||
loops here. */
|
||||
/* We store just pointers to loops here.
|
||||
Note that a loop in this array may actually be NULL, if the loop
|
||||
has been removed and the entire loops structure has not been
|
||||
recomputed since that time. */
|
||||
struct loop **parray;
|
||||
|
||||
/* Pointer to root of loop hierarchy tree. */
|
||||
@ -240,45 +172,45 @@ struct loops
|
||||
|
||||
/* Headers shared by multiple loops that should be merged. */
|
||||
sbitmap shared_headers;
|
||||
|
||||
/* State of loops. */
|
||||
int state;
|
||||
};
|
||||
|
||||
/* Flags for loop discovery. */
|
||||
/* The loop tree currently optimized. */
|
||||
|
||||
#define LOOP_TREE 1 /* Build loop hierarchy tree. */
|
||||
#define LOOP_PRE_HEADER 2 /* Analyze loop preheader. */
|
||||
#define LOOP_ENTRY_EDGES 4 /* Find entry edges. */
|
||||
#define LOOP_EXIT_EDGES 8 /* Find exit edges. */
|
||||
#define LOOP_EDGES (LOOP_ENTRY_EDGES | LOOP_EXIT_EDGES)
|
||||
#define LOOP_ALL 15 /* All of the above */
|
||||
extern struct loops *current_loops;
|
||||
|
||||
/* Loop recognition. */
|
||||
extern int flow_loops_find (struct loops *, int flags);
|
||||
extern int flow_loops_update (struct loops *, int flags);
|
||||
extern int flow_loops_find (struct loops *);
|
||||
extern void flow_loops_free (struct loops *);
|
||||
extern void flow_loops_dump (const struct loops *, FILE *,
|
||||
void (*)(const struct loop *, FILE *, int), int);
|
||||
extern void flow_loop_dump (const struct loop *, FILE *,
|
||||
void (*)(const struct loop *, FILE *, int), int);
|
||||
extern int flow_loop_scan (struct loop *, int);
|
||||
extern void flow_loop_free (struct loop *);
|
||||
int flow_loop_nodes_find (basic_block, struct loop *);
|
||||
void fix_loop_structure (struct loops *, bitmap changed_bbs);
|
||||
void mark_irreducible_loops (struct loops *);
|
||||
void mark_single_exit_loops (struct loops *);
|
||||
|
||||
/* Loop data structure manipulation/querying. */
|
||||
extern void flow_loop_tree_node_add (struct loop *, struct loop *);
|
||||
extern void flow_loop_tree_node_remove (struct loop *);
|
||||
extern bool flow_loop_outside_edge_p (const struct loop *, edge);
|
||||
extern bool flow_loop_nested_p (const struct loop *, const struct loop *);
|
||||
extern bool flow_bb_inside_loop_p (const struct loop *, const basic_block);
|
||||
extern struct loop * find_common_loop (struct loop *, struct loop *);
|
||||
struct loop *superloop_at_depth (struct loop *, unsigned);
|
||||
extern unsigned tree_num_loop_insns (struct loop *);
|
||||
extern int num_loop_insns (struct loop *);
|
||||
extern int average_num_loop_insns (struct loop *);
|
||||
extern unsigned get_loop_level (const struct loop *);
|
||||
extern bool loop_exit_edge_p (const struct loop *, edge);
|
||||
extern void mark_loop_exit_edges (struct loops *);
|
||||
|
||||
/* Loops & cfg manipulation. */
|
||||
extern basic_block *get_loop_body (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_dom_order (const struct loop *);
|
||||
extern basic_block *get_loop_body_in_bfs_order (const struct loop *);
|
||||
extern edge *get_loop_exit_edges (const struct loop *, unsigned *);
|
||||
extern unsigned num_loop_branches (const struct loop *);
|
||||
|
||||
extern edge loop_preheader_edge (const struct loop *);
|
||||
extern edge loop_latch_edge (const struct loop *);
|
||||
@ -286,7 +218,6 @@ extern edge loop_latch_edge (const struct loop *);
|
||||
extern void add_bb_to_loop (basic_block, struct loop *);
|
||||
extern void remove_bb_from_loops (basic_block);
|
||||
|
||||
extern void cancel_loop (struct loops *, struct loop *);
|
||||
extern void cancel_loop_tree (struct loops *, struct loop *);
|
||||
|
||||
extern basic_block loop_split_edge_with (edge, rtx);
|
||||
@ -303,28 +234,156 @@ extern void force_single_succ_latches (struct loops *);
|
||||
extern void verify_loop_structure (struct loops *);
|
||||
|
||||
/* Loop analysis. */
|
||||
extern bool simple_loop_p (struct loop *, struct loop_desc *);
|
||||
extern rtx count_loop_iterations (struct loop_desc *, rtx, rtx);
|
||||
extern bool just_once_each_iteration_p (struct loop *, basic_block);
|
||||
extern bool just_once_each_iteration_p (const struct loop *, basic_block);
|
||||
extern unsigned expected_loop_iterations (const struct loop *);
|
||||
extern rtx doloop_condition_get (rtx);
|
||||
|
||||
/* Loop manipulation. */
|
||||
extern bool can_duplicate_loop_p (struct loop *loop);
|
||||
|
||||
#define DLTHE_FLAG_UPDATE_FREQ 1 /* Update frequencies in
|
||||
duplicate_loop_to_header_edge. */
|
||||
#define DLTHE_RECORD_COPY_NUMBER 2 /* Record copy number in the aux
|
||||
field of newly create BB. */
|
||||
#define DLTHE_FLAG_COMPLETTE_PEEL 4 /* Update frequencies expecting
|
||||
a complete peeling. */
|
||||
|
||||
extern int duplicate_loop_to_header_edge (struct loop *, edge, struct loops *,
|
||||
unsigned, sbitmap, edge, edge *,
|
||||
unsigned *, int);
|
||||
extern struct loop *loopify (struct loops *, edge, edge, basic_block);
|
||||
extern void unloop (struct loops *, struct loop *);
|
||||
extern struct loop * duplicate_loop (struct loops *, struct loop *,
|
||||
struct loop *);
|
||||
extern bool duplicate_loop_to_header_edge (struct loop *, edge, struct loops *,
|
||||
unsigned, sbitmap, edge, edge *,
|
||||
unsigned *, int);
|
||||
extern struct loop *loopify (struct loops *, edge, edge,
|
||||
basic_block, edge, edge, bool);
|
||||
struct loop * loop_version (struct loops *, struct loop *, void *,
|
||||
basic_block *, bool);
|
||||
extern bool remove_path (struct loops *, edge);
|
||||
extern edge split_loop_bb (basic_block, rtx);
|
||||
|
||||
/* Induction variable analysis. */
|
||||
|
||||
/* The description of induction variable. The things are a bit complicated
|
||||
due to need to handle subregs and extends. The value of the object described
|
||||
by it can be obtained as follows (all computations are done in extend_mode):
|
||||
|
||||
Value in i-th iteration is
|
||||
delta + mult * extend_{extend_mode} (subreg_{mode} (base + i * step)).
|
||||
|
||||
If first_special is true, the value in the first iteration is
|
||||
delta + mult * base
|
||||
|
||||
If extend = UNKNOWN, first_special must be false, delta 0, mult 1 and value is
|
||||
subreg_{mode} (base + i * step)
|
||||
|
||||
The get_iv_value function can be used to obtain these expressions.
|
||||
|
||||
??? Add a third mode field that would specify the mode in that inner
|
||||
computation is done, which would enable it to be different from the
|
||||
outer one? */
|
||||
|
||||
struct rtx_iv
|
||||
{
|
||||
/* Its base and step (mode of base and step is supposed to be extend_mode,
|
||||
see the description above). */
|
||||
rtx base, step;
|
||||
|
||||
/* The type of extend applied to it (SIGN_EXTEND, ZERO_EXTEND or UNKNOWN). */
|
||||
enum rtx_code extend;
|
||||
|
||||
/* Operations applied in the extended mode. */
|
||||
rtx delta, mult;
|
||||
|
||||
/* The mode it is extended to. */
|
||||
enum machine_mode extend_mode;
|
||||
|
||||
/* The mode the variable iterates in. */
|
||||
enum machine_mode mode;
|
||||
|
||||
/* Whether the first iteration needs to be handled specially. */
|
||||
unsigned first_special : 1;
|
||||
};
|
||||
|
||||
/* The description of an exit from the loop and of the number of iterations
|
||||
till we take the exit. */
|
||||
|
||||
struct niter_desc
|
||||
{
|
||||
/* The edge out of the loop. */
|
||||
edge out_edge;
|
||||
|
||||
/* The other edge leading from the condition. */
|
||||
edge in_edge;
|
||||
|
||||
/* True if we are able to say anything about number of iterations of the
|
||||
loop. */
|
||||
bool simple_p;
|
||||
|
||||
/* True if the loop iterates the constant number of times. */
|
||||
bool const_iter;
|
||||
|
||||
/* Number of iterations if constant. */
|
||||
unsigned HOST_WIDEST_INT niter;
|
||||
|
||||
/* Upper bound on the number of iterations. */
|
||||
unsigned HOST_WIDEST_INT niter_max;
|
||||
|
||||
/* Assumptions under that the rest of the information is valid. */
|
||||
rtx assumptions;
|
||||
|
||||
/* Assumptions under that the loop ends before reaching the latch,
|
||||
even if value of niter_expr says otherwise. */
|
||||
rtx noloop_assumptions;
|
||||
|
||||
/* Condition under that the loop is infinite. */
|
||||
rtx infinite;
|
||||
|
||||
/* Whether the comparison is signed. */
|
||||
bool signed_p;
|
||||
|
||||
/* The mode in that niter_expr should be computed. */
|
||||
enum machine_mode mode;
|
||||
|
||||
/* The number of iterations of the loop. */
|
||||
rtx niter_expr;
|
||||
};
|
||||
|
||||
extern void iv_analysis_loop_init (struct loop *);
|
||||
extern bool iv_analyze (rtx, rtx, struct rtx_iv *);
|
||||
extern bool iv_analyze_result (rtx, rtx, struct rtx_iv *);
|
||||
extern bool iv_analyze_expr (rtx, rtx, enum machine_mode, struct rtx_iv *);
|
||||
extern rtx get_iv_value (struct rtx_iv *, rtx);
|
||||
extern bool biv_p (rtx, rtx);
|
||||
extern void find_simple_exit (struct loop *, struct niter_desc *);
|
||||
extern void iv_analysis_done (void);
|
||||
extern struct df *iv_current_loop_df (void);
|
||||
|
||||
extern struct niter_desc *get_simple_loop_desc (struct loop *loop);
|
||||
extern void free_simple_loop_desc (struct loop *loop);
|
||||
|
||||
static inline struct niter_desc *
|
||||
simple_loop_desc (struct loop *loop)
|
||||
{
|
||||
return (struct niter_desc *) loop->aux;
|
||||
}
|
||||
|
||||
/* The properties of the target. */
|
||||
|
||||
extern unsigned target_avail_regs; /* Number of available registers. */
|
||||
extern unsigned target_res_regs; /* Number of reserved registers. */
|
||||
extern unsigned target_small_cost; /* The cost for register when there
|
||||
is a free one. */
|
||||
extern unsigned target_pres_cost; /* The cost for register when there are
|
||||
not too many free ones. */
|
||||
extern unsigned target_spill_cost; /* The cost for register when we need
|
||||
to spill. */
|
||||
|
||||
/* Register pressure estimation for induction variable optimizations & loop
|
||||
invariant motion. */
|
||||
extern unsigned global_cost_for_size (unsigned, unsigned, unsigned);
|
||||
extern void init_set_costs (void);
|
||||
|
||||
/* Loop optimizer initialization. */
|
||||
extern struct loops *loop_optimizer_init (FILE *);
|
||||
extern void loop_optimizer_finalize (struct loops *, FILE *);
|
||||
extern struct loops *loop_optimizer_init (unsigned);
|
||||
extern void loop_optimizer_finalize (struct loops *);
|
||||
|
||||
/* Optimization passes. */
|
||||
extern void unswitch_loops (struct loops *);
|
||||
@ -337,5 +396,8 @@ enum
|
||||
};
|
||||
|
||||
extern void unroll_and_peel_loops (struct loops *, int);
|
||||
extern bool is_bct_cond (rtx);
|
||||
extern rtx get_var_set_from_bct (rtx);
|
||||
extern void doloop_optimize_loops (struct loops *);
|
||||
extern void move_loop_invariants (struct loops *);
|
||||
extern void record_estimate (struct loop *, tree, tree, tree);
|
||||
|
||||
#endif /* GCC_CFGLOOP_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1857
contrib/gcc/cfgrtl.c
1857
contrib/gcc/cfgrtl.c
File diff suppressed because it is too large
Load Diff
1208
contrib/gcc/cgraph.c
1208
contrib/gcc/cgraph.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Callgraph handling code.
|
||||
Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Contributed by Jan Hubicka
|
||||
|
||||
This file is part of GCC.
|
||||
@ -16,11 +16,35 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_CGRAPH_H
|
||||
#define GCC_CGRAPH_H
|
||||
#include "tree.h"
|
||||
#include "basic-block.h"
|
||||
|
||||
enum availability
|
||||
{
|
||||
/* Not yet set by cgraph_function_body_availability. */
|
||||
AVAIL_UNSET,
|
||||
/* Function body/variable initializer is unknown. */
|
||||
AVAIL_NOT_AVAILABLE,
|
||||
/* Function body/variable initializer is known but might be replaced
|
||||
by a different one from other compilation unit and thus needs to
|
||||
be dealt with a care. Like AVAIL_NOT_AVAILABLE it can have
|
||||
arbitrary side effects on escaping variables and functions, while
|
||||
like AVAILABLE it might access static variables. */
|
||||
AVAIL_OVERWRITABLE,
|
||||
/* Function body/variable initializer is known and will be used in final
|
||||
program. */
|
||||
AVAIL_AVAILABLE,
|
||||
/* Function body/variable initializer is known and all it's uses are explicitly
|
||||
visible within current unit (ie it's address is never taken and it is not
|
||||
exported to other units).
|
||||
Currently used only for functions. */
|
||||
AVAIL_LOCAL
|
||||
};
|
||||
|
||||
/* Information about the function collected locally.
|
||||
Available after function is analyzed. */
|
||||
@ -31,18 +55,32 @@ struct cgraph_local_info GTY(())
|
||||
int self_insns;
|
||||
|
||||
/* Set when function function is visible in current compilation unit only
|
||||
and it's address is never taken. */
|
||||
bool local;
|
||||
and its address is never taken. */
|
||||
unsigned local : 1;
|
||||
|
||||
/* Set when function is visible by other units. */
|
||||
unsigned externally_visible : 1;
|
||||
|
||||
/* Set once it has been finalized so we consider it to be output. */
|
||||
bool finalized;
|
||||
unsigned finalized : 1;
|
||||
|
||||
/* False when there something makes inlining impossible (such as va_arg). */
|
||||
bool inlinable;
|
||||
/* True when function should be inlined independently on it's size. */
|
||||
bool disregard_inline_limits;
|
||||
unsigned inlinable : 1;
|
||||
|
||||
/* True when function should be inlined independently on its size. */
|
||||
unsigned disregard_inline_limits : 1;
|
||||
|
||||
/* True when the function has been originally extern inline, but it is
|
||||
redefined now. */
|
||||
bool redefined_extern_inline;
|
||||
unsigned redefined_extern_inline : 1;
|
||||
|
||||
/* True if statics_read_for_function and
|
||||
statics_written_for_function contain valid data. */
|
||||
unsigned for_functions_valid : 1;
|
||||
|
||||
/* True if the function is going to be emitted in some other translation
|
||||
unit, referenced from vtable. */
|
||||
unsigned vtable_method : 1;
|
||||
};
|
||||
|
||||
/* Information about the function that needs to be computed globally
|
||||
@ -50,21 +88,16 @@ struct cgraph_local_info GTY(())
|
||||
|
||||
struct cgraph_global_info GTY(())
|
||||
{
|
||||
/* For inline clones this points to the function they will be inlined into. */
|
||||
struct cgraph_node *inlined_to;
|
||||
|
||||
/* Estimated size of the function after inlining. */
|
||||
int insns;
|
||||
|
||||
/* Number of times given function will be cloned during output. */
|
||||
int cloned_times;
|
||||
/* Estimated growth after inlining. INT_MIN if not computed. */
|
||||
int estimated_growth;
|
||||
|
||||
/* Set when the function will be inlined exactly once. */
|
||||
bool inline_once;
|
||||
|
||||
/* Set to true for all reachable functions before inlining is decided.
|
||||
Once we inline all calls to the function and the function is local,
|
||||
it is set to false. */
|
||||
bool will_be_output;
|
||||
|
||||
/* Set iff at least one of the caller edges has inline_call flag set. */
|
||||
/* Set iff the function has been inlined at least once. */
|
||||
bool inlined;
|
||||
};
|
||||
|
||||
@ -73,12 +106,9 @@ struct cgraph_global_info GTY(())
|
||||
|
||||
struct cgraph_rtl_info GTY(())
|
||||
{
|
||||
bool const_function;
|
||||
bool pure_function;
|
||||
int preferred_incoming_stack_boundary;
|
||||
};
|
||||
|
||||
|
||||
/* The cgraph data structure.
|
||||
Each function decl has assigned cgraph_node listing callees and callers. */
|
||||
|
||||
@ -97,96 +127,208 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
|
||||
struct cgraph_node *next_nested;
|
||||
/* Pointer to the next function in cgraph_nodes_queue. */
|
||||
struct cgraph_node *next_needed;
|
||||
PTR GTY ((skip (""))) aux;
|
||||
/* Pointer to the next clone. */
|
||||
struct cgraph_node *next_clone;
|
||||
struct cgraph_node *prev_clone;
|
||||
/* Pointer to a single unique cgraph node for this function. If the
|
||||
function is to be output, this is the copy that will survive. */
|
||||
struct cgraph_node *master_clone;
|
||||
/* For functions with many calls sites it holds map from call expression
|
||||
to the edge to speed up cgraph_edge function. */
|
||||
htab_t GTY((param_is (struct cgraph_edge))) call_site_hash;
|
||||
|
||||
PTR GTY ((skip)) aux;
|
||||
|
||||
struct cgraph_local_info local;
|
||||
struct cgraph_global_info global;
|
||||
struct cgraph_rtl_info rtl;
|
||||
|
||||
/* Expected number of executions: calculated in profile.c. */
|
||||
gcov_type count;
|
||||
/* Unique id of the node. */
|
||||
int uid;
|
||||
/* Ordering of all cgraph nodes. */
|
||||
int order;
|
||||
|
||||
/* Set when function must be output - it is externally visible
|
||||
or it's address is taken. */
|
||||
bool needed;
|
||||
or its address is taken. */
|
||||
unsigned needed : 1;
|
||||
/* Set when function is reachable by call from other function
|
||||
that is either reachable or needed. */
|
||||
bool reachable;
|
||||
unsigned reachable : 1;
|
||||
/* Set once the function is lowered (i.e. its CFG is built). */
|
||||
unsigned lowered : 1;
|
||||
/* Set once the function has been instantiated and its callee
|
||||
lists created. */
|
||||
bool analyzed;
|
||||
unsigned analyzed : 1;
|
||||
/* Set when function is scheduled to be assembled. */
|
||||
bool output;
|
||||
unsigned output : 1;
|
||||
/* Set for aliases once they got through assemble_alias. */
|
||||
unsigned alias : 1;
|
||||
|
||||
/* In non-unit-at-a-time mode the function body of inline candidates is saved
|
||||
into clone before compiling so the function in original form can be
|
||||
inlined later. This pointer points to the clone. */
|
||||
tree inline_decl;
|
||||
};
|
||||
|
||||
struct cgraph_edge GTY(())
|
||||
struct cgraph_edge GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller")))
|
||||
{
|
||||
struct cgraph_node *caller;
|
||||
struct cgraph_node *callee;
|
||||
struct cgraph_edge *prev_caller;
|
||||
struct cgraph_edge *next_caller;
|
||||
struct cgraph_edge *prev_callee;
|
||||
struct cgraph_edge *next_callee;
|
||||
tree call_stmt;
|
||||
PTR GTY ((skip (""))) aux;
|
||||
/* When NULL, inline this call. When non-NULL, points to the explanation
|
||||
why function was not inlined. */
|
||||
const char *inline_failed;
|
||||
/* Expected number of executions: calculated in profile.c. */
|
||||
gcov_type count;
|
||||
/* Depth of loop nest, 1 means no loop nest. */
|
||||
int loop_nest;
|
||||
};
|
||||
|
||||
typedef struct cgraph_edge *cgraph_edge_p;
|
||||
|
||||
DEF_VEC_P(cgraph_edge_p);
|
||||
DEF_VEC_ALLOC_P(cgraph_edge_p,heap);
|
||||
|
||||
/* The cgraph_varpool data structure.
|
||||
Each static variable decl has assigned cgraph_varpool_node. */
|
||||
|
||||
struct cgraph_varpool_node GTY(())
|
||||
{
|
||||
tree decl;
|
||||
/* Pointer to the next function in cgraph_varpool_nodes. */
|
||||
struct cgraph_varpool_node *next;
|
||||
/* Pointer to the next function in cgraph_varpool_nodes_queue. */
|
||||
struct cgraph_varpool_node *next_needed;
|
||||
/* Ordering of all cgraph nodes. */
|
||||
int order;
|
||||
|
||||
/* Set when function must be output - it is externally visible
|
||||
or it's address is taken. */
|
||||
bool needed;
|
||||
or its address is taken. */
|
||||
unsigned needed : 1;
|
||||
/* Needed variables might become dead by optimization. This flag
|
||||
forces the variable to be output even if it appears dead otherwise. */
|
||||
unsigned force_output : 1;
|
||||
/* Set once the variable has been instantiated and its callee
|
||||
lists created. */
|
||||
unsigned analyzed : 1;
|
||||
/* Set once it has been finalized so we consider it to be output. */
|
||||
bool finalized;
|
||||
/* Set when function is scheduled to be assembled. */
|
||||
bool output;
|
||||
unsigned finalized : 1;
|
||||
/* Set when variable is scheduled to be assembled. */
|
||||
unsigned output : 1;
|
||||
/* Set when function is visible by other units. */
|
||||
unsigned externally_visible : 1;
|
||||
/* Set for aliases once they got through assemble_alias. */
|
||||
unsigned alias : 1;
|
||||
};
|
||||
|
||||
/* Every top level asm statement is put into a cgraph_asm_node. */
|
||||
|
||||
struct cgraph_asm_node GTY(())
|
||||
{
|
||||
/* Next asm node. */
|
||||
struct cgraph_asm_node *next;
|
||||
/* String for this asm node. */
|
||||
tree asm_str;
|
||||
/* Ordering of all cgraph nodes. */
|
||||
int order;
|
||||
};
|
||||
|
||||
extern GTY(()) struct cgraph_node *cgraph_nodes;
|
||||
extern GTY(()) int cgraph_n_nodes;
|
||||
extern GTY(()) int cgraph_max_uid;
|
||||
extern bool cgraph_global_info_ready;
|
||||
extern bool cgraph_function_flags_ready;
|
||||
extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
|
||||
extern FILE *cgraph_dump_file;
|
||||
extern GTY(()) struct cgraph_node *cgraph_expand_queue;
|
||||
|
||||
extern GTY(()) int cgraph_varpool_n_nodes;
|
||||
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
|
||||
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
|
||||
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
|
||||
|
||||
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
|
||||
extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
|
||||
extern GTY(()) int cgraph_order;
|
||||
|
||||
/* In cgraph.c */
|
||||
void dump_cgraph (FILE *);
|
||||
void cgraph_remove_edge (struct cgraph_node *, struct cgraph_node *);
|
||||
void cgraph_remove_call (tree, tree);
|
||||
void dump_cgraph_node (FILE *, struct cgraph_node *);
|
||||
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
|
||||
void dump_varpool (FILE *);
|
||||
void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
|
||||
void cgraph_remove_edge (struct cgraph_edge *);
|
||||
void cgraph_remove_node (struct cgraph_node *);
|
||||
struct cgraph_edge *cgraph_record_call (tree, tree);
|
||||
struct cgraph_node *cgraph_node (tree decl);
|
||||
struct cgraph_node *cgraph_node_for_identifier (tree id);
|
||||
bool cgraph_calls_p (tree, tree);
|
||||
void cgraph_node_remove_callees (struct cgraph_node *node);
|
||||
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
|
||||
struct cgraph_node *,
|
||||
tree, gcov_type, int);
|
||||
struct cgraph_node *cgraph_node (tree);
|
||||
struct cgraph_node *cgraph_node_for_asm (tree asmname);
|
||||
struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree);
|
||||
void cgraph_set_call_stmt (struct cgraph_edge *, tree);
|
||||
struct cgraph_local_info *cgraph_local_info (tree);
|
||||
struct cgraph_global_info *cgraph_global_info (tree);
|
||||
struct cgraph_rtl_info *cgraph_rtl_info (tree);
|
||||
const char * cgraph_node_name (struct cgraph_node *);
|
||||
struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
|
||||
struct cgraph_node *,
|
||||
tree, gcov_type, int, bool);
|
||||
struct cgraph_node * cgraph_clone_node (struct cgraph_node *, gcov_type,
|
||||
int, bool);
|
||||
|
||||
struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
|
||||
struct cgraph_varpool_node *cgraph_varpool_node_for_identifier (tree id);
|
||||
struct cgraph_varpool_node *cgraph_varpool_node (tree);
|
||||
struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
|
||||
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
|
||||
void cgraph_varpool_finalize_decl (tree);
|
||||
bool cgraph_varpool_assemble_pending_decls (void);
|
||||
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
|
||||
|
||||
struct cgraph_asm_node *cgraph_add_asm_node (tree);
|
||||
|
||||
bool cgraph_function_possibly_inlined_p (tree);
|
||||
void cgraph_unnest_node (struct cgraph_node *);
|
||||
void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
|
||||
void cgraph_varpool_reset_queue (void);
|
||||
bool decide_is_variable_needed (struct cgraph_varpool_node *, tree);
|
||||
|
||||
enum availability cgraph_function_body_availability (struct cgraph_node *);
|
||||
enum availability cgraph_variable_initializer_availability (struct cgraph_varpool_node *);
|
||||
bool cgraph_is_master_clone (struct cgraph_node *);
|
||||
struct cgraph_node *cgraph_master_clone (struct cgraph_node *);
|
||||
void cgraph_add_new_function (tree);
|
||||
|
||||
/* In cgraphunit.c */
|
||||
bool cgraph_assemble_pending_functions (void);
|
||||
bool cgraph_varpool_assemble_pending_decls (void);
|
||||
void cgraph_finalize_function (tree, bool);
|
||||
void cgraph_finalize_compilation_unit (void);
|
||||
void cgraph_create_edges (tree, tree);
|
||||
void cgraph_optimize (void);
|
||||
void cgraph_mark_needed_node (struct cgraph_node *);
|
||||
void cgraph_mark_reachable_node (struct cgraph_node *);
|
||||
bool cgraph_inline_p (tree, tree, const char **reason);
|
||||
bool cgraph_inline_p (struct cgraph_edge *, const char **reason);
|
||||
bool cgraph_preserve_function_body_p (tree);
|
||||
void verify_cgraph (void);
|
||||
void verify_cgraph_node (struct cgraph_node *);
|
||||
void cgraph_build_static_cdtor (char which, tree body, int priority);
|
||||
void cgraph_reset_static_var_maps (void);
|
||||
void init_cgraph (void);
|
||||
struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
|
||||
VEC(cgraph_edge_p,heap)*,
|
||||
varray_type);
|
||||
void cgraph_analyze_function (struct cgraph_node *);
|
||||
struct cgraph_node *save_inline_function_body (struct cgraph_node *);
|
||||
|
||||
/* In ipa.c */
|
||||
bool cgraph_remove_unreachable_nodes (bool, FILE *);
|
||||
int cgraph_postorder (struct cgraph_node **);
|
||||
|
||||
/* In ipa-inline.c */
|
||||
bool cgraph_decide_inlining_incrementally (struct cgraph_node *, bool);
|
||||
void cgraph_clone_inlined_nodes (struct cgraph_edge *, bool, bool);
|
||||
void cgraph_mark_inline_edge (struct cgraph_edge *, bool);
|
||||
bool cgraph_default_inline_p (struct cgraph_node *, const char **);
|
||||
#endif /* GCC_CGRAPH_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* Header file for collect/tlink routines.
|
||||
Copyright (C) 1998, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1998, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
@ -15,31 +15,32 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_COLLECT2_H
|
||||
#define GCC_COLLECT2_H
|
||||
|
||||
extern void do_tlink (char **, char **);
|
||||
|
||||
extern void collect_execute (const char *, char **, const char *);
|
||||
extern struct pex_obj *collect_execute (const char *, char **, const char *,
|
||||
const char *);
|
||||
|
||||
extern void collect_exit (int) ATTRIBUTE_NORETURN;
|
||||
|
||||
extern int collect_wait (const char *);
|
||||
extern int collect_wait (const char *, struct pex_obj *);
|
||||
|
||||
extern void dump_file (const char *);
|
||||
extern void dump_file (const char *, FILE *);
|
||||
|
||||
extern int file_exists (const char *);
|
||||
|
||||
extern const char *ldout;
|
||||
extern const char *lderrout;
|
||||
extern const char *c_file_name;
|
||||
extern struct obstack temporary_obstack;
|
||||
extern char *temporary_firstobj;
|
||||
extern int vflag, debug;
|
||||
|
||||
extern void fancy_abort (void) ATTRIBUTE_NORETURN;
|
||||
extern void error (const char *, ...) ATTRIBUTE_PRINTF_1;
|
||||
extern void notice (const char *, ...) ATTRIBUTE_PRINTF_1;
|
||||
extern void fatal (const char *, ...) ATTRIBUTE_PRINTF_1 ATTRIBUTE_NORETURN;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,8 +15,8 @@ for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* None of the things in the files exist if we don't use CC0. */
|
||||
|
||||
|
@ -16,8 +16,8 @@
|
||||
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with GCC; see the file COPYING. If not, write to the Free
|
||||
#Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#02111-1307, USA.
|
||||
#Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#02110-1301, USA.
|
||||
|
||||
# This is the GCC build-specific configuration file
|
||||
# where a configuration type is mapped to different system-specific
|
||||
@ -90,15 +90,10 @@ case $build in
|
||||
build_install_headers_dir=install-headers-cpio
|
||||
;;
|
||||
i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4* )
|
||||
build_xm_defines="SMALL_ARG_MAX"
|
||||
build_install_headers_dir=install-headers-cpio
|
||||
;;
|
||||
i[34567]86-*-solaris2*)
|
||||
build_xm_defines="SMALL_ARG_MAX"
|
||||
;;
|
||||
i[34567]86-*-sysv4*)
|
||||
# Intel x86 running system V r4
|
||||
build_xm_defines="SMALL_ARG_MAX"
|
||||
build_install_headers_dir=install-headers-cpio
|
||||
;;
|
||||
i[34567]86-*-udk*)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
# GCC host-specific configuration file.
|
||||
# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2006
|
||||
# Free Software Foundation, Inc.
|
||||
|
||||
#This file is part of GCC.
|
||||
@ -16,8 +16,8 @@
|
||||
|
||||
#You should have received a copy of the GNU General Public License
|
||||
#along with GCC; see the file COPYING. If not, write to the Free
|
||||
#Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
#02111-1307, USA.
|
||||
#Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
#02110-1301, USA.
|
||||
|
||||
# This is the GCC host-specific configuration file
|
||||
# where a configuration type is mapped to different system-specific
|
||||
@ -49,6 +49,13 @@
|
||||
# be linked into the gcc driver.
|
||||
#
|
||||
# out_host_hook_obj An object file that provides the host hooks.
|
||||
#
|
||||
# host_can_use_collect2 Set to yes normally; to no if the host cannot
|
||||
# link or otherwise use collect2
|
||||
# use_long_long_for_widest_fast_int Set this to 'yes' if 'long long'
|
||||
# (or '__int64') is wider than 'long' but still
|
||||
# efficeiently supported by the host hardware.
|
||||
# Only affects compile speed. Default is 'no'.
|
||||
|
||||
# When setting any of these variables, check to see if a corresponding
|
||||
# variable is present in config.build; if so, you will likely want to
|
||||
@ -62,6 +69,8 @@ host_exeext=
|
||||
host_extra_objs=
|
||||
host_extra_gcc_objs=
|
||||
out_host_hook_obj=host-default.o
|
||||
host_can_use_collect2=yes
|
||||
use_long_long_for_widest_fast_int=no
|
||||
|
||||
# Unsupported hosts list. Generally, only include hosts known to fail here,
|
||||
# since we allow hosts not listed to be supported generically.
|
||||
@ -76,12 +85,35 @@ case ${host} in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Common parts for widely ported systems.
|
||||
case ${host} in
|
||||
*-darwin*)
|
||||
# Generic darwin host support.
|
||||
out_host_hook_obj=host-darwin.o
|
||||
host_xmake_file="${host_xmake_file} x-darwin"
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${host} in
|
||||
i[34567]86-*-* \
|
||||
| x86_64-*-* )
|
||||
case ${target} in
|
||||
i[34567]86-*-* \
|
||||
| x86_64-*-* )
|
||||
host_extra_gcc_objs="driver-i386.o"
|
||||
host_xmake_file="${host_xmake_file} i386/x-i386"
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
# Machine-specific settings.
|
||||
case ${host} in
|
||||
alpha*-dec-*vms*)
|
||||
host_xm_file=alpha/xm-vms.h
|
||||
host_xmake_file=alpha/x-vms
|
||||
host_xmake_file="${host_xmake_file} alpha/x-vms"
|
||||
host_exeext=.exe
|
||||
host_can_use_collect2=no
|
||||
# This removes the cpu type and manufacturer components and
|
||||
# replaces "." with "_" in the operating system version.
|
||||
target_noncanonical=`echo $host | sed 's/.*-.*-\(.*\)$/\1/' | sed 's/\./_/g'`
|
||||
@ -89,40 +121,36 @@ case ${host} in
|
||||
local_prefix=/gnu
|
||||
;;
|
||||
hppa1.1-*-pro*)
|
||||
host_xmake_file="pa/x-ada"
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada"
|
||||
;;
|
||||
hppa1.1-*-osf*)
|
||||
host_xmake_file="pa/x-ada"
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada"
|
||||
;;
|
||||
hppa1.1-*-rtems*)
|
||||
host_xmake_file="pa/x-ada"
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada"
|
||||
;;
|
||||
hppa1.1-*-bsd*)
|
||||
host_xmake_file="pa/x-ada"
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada"
|
||||
;;
|
||||
hppa1.0-*-hpux10* | hppa1.1-*-hpux10* | hppa2*-*-hpux10*)
|
||||
out_host_hook_obj=host-hpux.o
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada-hpux10 x-hpux"
|
||||
;;
|
||||
hppa1.0-*-hpux10* | hppa1.1-*-hpux10* | hppa2*-*-hpux10* | \
|
||||
hppa1.0-*-hpux11* | hppa1.1-*-hpux11* | hppa2*-*-hpux11* | \
|
||||
hppa*64*-*-hpux11*)
|
||||
out_host_hook_obj=pa-host.o
|
||||
host_xmake_file=pa/x-hpux
|
||||
out_host_hook_obj=host-hpux.o
|
||||
host_xmake_file="${host_xmake_file} pa/x-ada x-hpux"
|
||||
;;
|
||||
hppa*-*-linux*)
|
||||
out_host_hook_obj=pa-host.o
|
||||
host_xmake_file=pa/x-linux
|
||||
out_host_hook_obj=host-hpux.o
|
||||
host_xmake_file="${host_xmake_file} x-hpux"
|
||||
;;
|
||||
i370-*-opened* | i370-*-mvs* ) # IBM 360/370/390 Architecture
|
||||
host_xm_defines='FATAL_EXIT_CODE=12'
|
||||
;;
|
||||
i[34567]86-sequent-ptx4*)
|
||||
host_xm_defines="SMALL_ARG_MAX"
|
||||
;;
|
||||
i[34567]86-*-solaris2*)
|
||||
host_xm_defines="SMALL_ARG_MAX"
|
||||
out_host_hook_obj=host-solaris.o
|
||||
host_xmake_file=x-solaris
|
||||
;;
|
||||
i[34567]86-*-sysv4*) # Intel 80386's running System V Release 4
|
||||
host_xm_defines="SMALL_ARG_MAX"
|
||||
host_xmake_file="${host_xmake_file} x-solaris"
|
||||
;;
|
||||
i[34567]86-pc-msdosdjgpp*)
|
||||
host_xm_file=i386/xm-djgpp.h
|
||||
@ -136,12 +164,15 @@ case ${host} in
|
||||
;;
|
||||
i[34567]86-*-pe | i[34567]86-*-cygwin*)
|
||||
host_xm_file=i386/xm-cygwin.h
|
||||
out_host_hook_obj=host-cygwin.o
|
||||
host_xmake_file="${host_xmake_file} i386/x-cygwin"
|
||||
host_exeext=.exe
|
||||
;;
|
||||
i[34567]86-*-mingw32*)
|
||||
host_xm_file=i386/xm-mingw32.h
|
||||
host_xmake_file=i386/x-mingw32
|
||||
host_xmake_file="${host_xmake_file} i386/x-mingw32"
|
||||
host_exeext=.exe
|
||||
out_host_hook_obj=host-mingw32.o
|
||||
;;
|
||||
i[34567]86-*-uwin*)
|
||||
echo "*** UWIN may not be used as a host platform because"
|
||||
@ -149,22 +180,34 @@ case ${host} in
|
||||
exit 1
|
||||
;;
|
||||
i[34567]86-*-interix3*)
|
||||
host_xmake_file="x-interix"
|
||||
host_xmake_file="${host_xmake_file} x-interix"
|
||||
;;
|
||||
i860-*-sysv4*)
|
||||
host_xmake_file=i860/x-sysv4
|
||||
i[34567]86-*-darwin* | x86_64-*-darwin*)
|
||||
out_host_hook_obj="${out_host_hook_obj} host-i386-darwin.o"
|
||||
host_xmake_file="${host_xmake_file} i386/x-darwin"
|
||||
;;
|
||||
powerpc-*-beos*)
|
||||
host_can_use_collect2=no
|
||||
;;
|
||||
powerpc-*-darwin*)
|
||||
# powerpc-darwin host support.
|
||||
out_host_hook_obj=host-darwin.o
|
||||
host_xmake_file=rs6000/x-darwin
|
||||
out_host_hook_obj="${out_host_hook_obj} host-ppc-darwin.o"
|
||||
host_xmake_file="${host_xmake_file} rs6000/x-darwin"
|
||||
;;
|
||||
powerpc64-*-darwin*)
|
||||
out_host_hook_obj="${out_host_hook_obj} host-ppc64-darwin.o"
|
||||
host_xmake_file="${host_xmake_file} rs6000/x-darwin64"
|
||||
;;
|
||||
*-*-solaris2*)
|
||||
out_host_hook_obj=host-solaris.o
|
||||
host_xmake_file=x-solaris
|
||||
host_xmake_file="${host_xmake_file} x-solaris"
|
||||
;;
|
||||
*-*-linux*)
|
||||
out_host_hook_obj=host-linux.o
|
||||
host_xmake_file=x-linux
|
||||
host_xmake_file="${host_xmake_file} x-linux"
|
||||
;;
|
||||
ia64-*-hpux*)
|
||||
use_long_long_for_widest_fast_int=yes
|
||||
out_host_hook_obj=host-hpux.o
|
||||
host_xmake_file="${host_xmake_file} x-hpux"
|
||||
;;
|
||||
esac
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -78,7 +78,7 @@ then the following rules must be obeyed:
|
||||
|
||||
* All externally visible functions which should be entered in
|
||||
Thumb mode must have the .thumb_func pseudo op specified just
|
||||
before their entry point. eg:
|
||||
before their entry point. e.g.:
|
||||
|
||||
.code 16
|
||||
.global function
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Definitions of target machine for GNU compiler, for Advanced RISC Machines
|
||||
ARM compilation, AOF Assembler.
|
||||
Copyright (C) 1995, 1996, 1997, 2000, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1995, 1996, 1997, 2000, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
|
||||
|
||||
This file is part of GCC.
|
||||
@ -17,8 +18,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
|
||||
|
||||
@ -34,8 +35,7 @@
|
||||
#define ENDFILE_SPEC "crtend.o%s"
|
||||
|
||||
#ifndef ASM_SPEC
|
||||
#define ASM_SPEC "%{g -g} -arch 4 \
|
||||
-apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/26bit}}"
|
||||
#define ASM_SPEC "%{g -g} -arch 4 -apcs 3/32bit"
|
||||
#endif
|
||||
|
||||
#ifndef LIB_SPEC
|
||||
@ -44,48 +44,6 @@
|
||||
|
||||
#define LIBGCC_SPEC "libgcc.a%s"
|
||||
|
||||
/* Dividing the Output into Sections (Text, Data, ...) */
|
||||
/* AOF Assembler syntax is a nightmare when it comes to areas, since once
|
||||
we change from one area to another, we can't go back again. Instead,
|
||||
we must create a new area with the same attributes and add the new output
|
||||
to that. Unfortunately, there is nothing we can do here to guarantee that
|
||||
two areas with the same attributes will be linked adjacently in the
|
||||
resulting executable, so we have to be careful not to do pc-relative
|
||||
addressing across such boundaries. */
|
||||
#define TEXT_SECTION_ASM_OP aof_text_section ()
|
||||
|
||||
#define DATA_SECTION_ASM_OP aof_data_section ()
|
||||
|
||||
#define EXTRA_SECTIONS in_zero_init, in_common
|
||||
|
||||
#define EXTRA_SECTION_FUNCTIONS \
|
||||
ZERO_INIT_SECTION \
|
||||
COMMON_SECTION
|
||||
|
||||
#define ZERO_INIT_SECTION \
|
||||
void \
|
||||
zero_init_section () \
|
||||
{ \
|
||||
static int zero_init_count = 1; \
|
||||
\
|
||||
if (in_section != in_zero_init) \
|
||||
{ \
|
||||
fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", \
|
||||
zero_init_count++); \
|
||||
in_section = in_zero_init; \
|
||||
} \
|
||||
}
|
||||
|
||||
/* Used by ASM_OUTPUT_COMMON (below) to tell varasm.c that we've
|
||||
changed areas. */
|
||||
#define COMMON_SECTION \
|
||||
void \
|
||||
common_section () \
|
||||
{ \
|
||||
if (in_section != in_common) \
|
||||
in_section = in_common; \
|
||||
}
|
||||
|
||||
#define CTOR_LIST_BEGIN \
|
||||
asm (CTORS_SECTION_ASM_OP); \
|
||||
extern func_ptr __CTOR_END__[1]; \
|
||||
@ -130,6 +88,8 @@
|
||||
whole table generation until the end of the function. */
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION 1
|
||||
|
||||
#define TARGET_ASM_INIT_SECTIONS aof_asm_init_sections
|
||||
|
||||
/* Some systems use __main in a way incompatible with its use in gcc, in these
|
||||
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
|
||||
give the same symbol without quotes for an alternative entry point. You
|
||||
@ -159,7 +119,7 @@
|
||||
/* Output of Uninitialized Variables. */
|
||||
|
||||
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
|
||||
(common_section (), \
|
||||
(in_section = NULL, \
|
||||
fprintf ((STREAM), "\tAREA "), \
|
||||
assemble_name ((STREAM), (NAME)), \
|
||||
fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
|
||||
@ -246,7 +206,12 @@ do { \
|
||||
"wr0", "wr1", "wr2", "wr3", \
|
||||
"wr4", "wr5", "wr6", "wr7", \
|
||||
"wr8", "wr9", "wr10", "wr11", \
|
||||
"wr12", "wr13", "wr14", "wr15" \
|
||||
"wr12", "wr13", "wr14", "wr15", \
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
|
||||
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
|
||||
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
|
||||
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
|
||||
"vfpcc" \
|
||||
}
|
||||
|
||||
#define ADDITIONAL_REGISTER_NAMES \
|
||||
@ -266,7 +231,23 @@ do { \
|
||||
{"r12", 12}, {"ip", 12}, \
|
||||
{"r13", 13}, {"sp", 13}, \
|
||||
{"r14", 14}, {"lr", 14}, \
|
||||
{"r15", 15}, {"pc", 15} \
|
||||
{"r15", 15}, {"pc", 15}, \
|
||||
{"d0", 63}, \
|
||||
{"d1", 65}, \
|
||||
{"d2", 67}, \
|
||||
{"d3", 69}, \
|
||||
{"d4", 71}, \
|
||||
{"d5", 73}, \
|
||||
{"d6", 75}, \
|
||||
{"d7", 77}, \
|
||||
{"d8", 79}, \
|
||||
{"d9", 81}, \
|
||||
{"d10", 83}, \
|
||||
{"d11", 85}, \
|
||||
{"d12", 87}, \
|
||||
{"d13", 89}, \
|
||||
{"d14", 91}, \
|
||||
{"d15", 93} \
|
||||
}
|
||||
|
||||
#define REGISTER_PREFIX "__"
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Definitions of target machine for GNU compiler, for ARM with a.out
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
|
||||
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2004
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk).
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef ASM_APP_ON
|
||||
#define ASM_APP_ON ""
|
||||
@ -49,7 +49,7 @@
|
||||
|
||||
/* The assembler's names for the registers. */
|
||||
#ifndef REGISTER_NAMES
|
||||
#define REGISTER_NAMES \
|
||||
#define REGISTER_NAMES \
|
||||
{ \
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
|
||||
"r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \
|
||||
@ -63,7 +63,12 @@
|
||||
"wr0", "wr1", "wr2", "wr3", \
|
||||
"wr4", "wr5", "wr6", "wr7", \
|
||||
"wr8", "wr9", "wr10", "wr11", \
|
||||
"wr12", "wr13", "wr14", "wr15" \
|
||||
"wr12", "wr13", "wr14", "wr15", \
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
|
||||
"s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
|
||||
"s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
|
||||
"s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
|
||||
"vfpcc" \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -152,7 +157,23 @@
|
||||
{"mvdx12", 39}, \
|
||||
{"mvdx13", 40}, \
|
||||
{"mvdx14", 41}, \
|
||||
{"mvdx15", 42} \
|
||||
{"mvdx15", 42}, \
|
||||
{"d0", 63}, \
|
||||
{"d1", 65}, \
|
||||
{"d2", 67}, \
|
||||
{"d3", 69}, \
|
||||
{"d4", 71}, \
|
||||
{"d5", 73}, \
|
||||
{"d6", 75}, \
|
||||
{"d7", 77}, \
|
||||
{"d8", 79}, \
|
||||
{"d9", 81}, \
|
||||
{"d10", 83}, \
|
||||
{"d11", 85}, \
|
||||
{"d12", 87}, \
|
||||
{"d13", 89}, \
|
||||
{"d14", 91}, \
|
||||
{"d15", 93}, \
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -172,19 +193,6 @@
|
||||
#define DBX_CONTIN_LENGTH 0
|
||||
#endif
|
||||
|
||||
/* Output a source filename for the debugger. RISCiX dbx insists that the
|
||||
``desc'' field is set to compiler version number >= 315 (sic). */
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM, NAME) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (STREAM, ".stabs "); \
|
||||
output_quoted_string (STREAM, NAME); \
|
||||
fprintf (STREAM, ",%d,0,315,%s\n", N_SO, <ext_label_name[1]); \
|
||||
text_section (); \
|
||||
(*targetm.asm_out.internal_label) (STREAM, "Ltext", 0); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Output a function label definition. */
|
||||
#ifndef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
|
||||
@ -265,7 +273,7 @@
|
||||
#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
|
||||
do \
|
||||
{ \
|
||||
bss_section (); \
|
||||
switch_to_section (bss_section); \
|
||||
ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
|
||||
ASM_OUTPUT_LABEL (STREAM, NAME); \
|
||||
fprintf (STREAM, "\t.space\t%d\n", (int)(SIZE)); \
|
||||
|
117
contrib/gcc/config/arm/arm-cores.def
Normal file
117
contrib/gcc/config/arm/arm-cores.def
Normal file
@ -0,0 +1,117 @@
|
||||
/* ARM CPU Cores
|
||||
Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||
Written by CodeSourcery, LLC
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
/* Before using #include to read this file, define a macro:
|
||||
|
||||
ARM_CORE(CORE_NAME, CORE_IDENT, ARCH, FLAGS, COSTS)
|
||||
|
||||
The CORE_NAME is the name of the core, represented as a string constant.
|
||||
The CORE_IDENT is the name of the core, represented as an identifier.
|
||||
ARCH is the architecture revision implemented by the chip.
|
||||
FLAGS are the bitwise-or of the traits that apply to that core.
|
||||
This need not include flags implied by the architecture.
|
||||
COSTS is the name of the rtx_costs routine to use.
|
||||
|
||||
If you update this table, you must update the "tune" attribute in
|
||||
arm.md.
|
||||
|
||||
Some tools assume no whitespace up to the first "," in each entry. */
|
||||
|
||||
/* V2/V2A Architecture Processors */
|
||||
ARM_CORE("arm2", arm2, 2, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm250", arm250, 2, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm3", arm3, 2, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
|
||||
/* V3 Architecture Processors */
|
||||
ARM_CORE("arm6", arm6, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm60", arm60, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm600", arm600, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm610", arm610, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm620", arm620, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm7", arm7, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm7d", arm7d, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm7di", arm7di, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm70", arm70, 3, FL_CO_PROC | FL_MODE26, slowmul)
|
||||
ARM_CORE("arm700", arm700, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm700i", arm700i, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm710", arm710, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm720", arm720, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm710c", arm710c, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm7100", arm7100, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
ARM_CORE("arm7500", arm7500, 3, FL_MODE26 | FL_WBUF, slowmul)
|
||||
/* Doesn't have an external co-proc, but does have embedded fpa. */
|
||||
ARM_CORE("arm7500fe", arm7500fe, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
|
||||
|
||||
/* V3M Architecture Processors */
|
||||
/* arm7m doesn't exist on its own, but only with D, ("and", and I), but
|
||||
those don't alter the code, so arm7m is sometimes used. */
|
||||
ARM_CORE("arm7m", arm7m, 3M, FL_CO_PROC | FL_MODE26, fastmul)
|
||||
ARM_CORE("arm7dm", arm7dm, 3M, FL_CO_PROC | FL_MODE26, fastmul)
|
||||
ARM_CORE("arm7dmi", arm7dmi, 3M, FL_CO_PROC | FL_MODE26, fastmul)
|
||||
|
||||
/* V4 Architecture Processors */
|
||||
ARM_CORE("arm8", arm8, 4, FL_MODE26 | FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm810", arm810, 4, FL_MODE26 | FL_LDSCHED, fastmul)
|
||||
ARM_CORE("strongarm", strongarm, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
|
||||
ARM_CORE("strongarm110", strongarm110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
|
||||
ARM_CORE("strongarm1100", strongarm1100, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
|
||||
ARM_CORE("strongarm1110", strongarm1110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
|
||||
|
||||
/* V4T Architecture Processors */
|
||||
ARM_CORE("arm7tdmi", arm7tdmi, 4T, FL_CO_PROC , fastmul)
|
||||
ARM_CORE("arm7tdmi-s", arm7tdmis, 4T, FL_CO_PROC , fastmul)
|
||||
ARM_CORE("arm710t", arm710t, 4T, FL_WBUF, fastmul)
|
||||
ARM_CORE("arm720t", arm720t, 4T, FL_WBUF, fastmul)
|
||||
ARM_CORE("arm740t", arm740t, 4T, FL_WBUF, fastmul)
|
||||
ARM_CORE("arm9", arm9, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm9tdmi", arm9tdmi, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm920", arm920, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm920t", arm920t, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm922t", arm922t, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm940t", arm940t, 4T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("ep9312", ep9312, 4T, FL_LDSCHED | FL_CIRRUS, fastmul)
|
||||
|
||||
/* V5T Architecture Processors */
|
||||
ARM_CORE("arm10tdmi", arm10tdmi, 5T, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm1020t", arm1020t, 5T, FL_LDSCHED, fastmul)
|
||||
|
||||
/* V5TE Architecture Processors */
|
||||
ARM_CORE("arm9e", arm9e, 5TE, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm946e-s", arm946es, 5TE, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm966e-s", arm966es, 5TE, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm968e-s", arm968es, 5TE, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm10e", arm10e, 5TE, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm1020e", arm1020e, 5TE, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("arm1022e", arm1022e, 5TE, FL_LDSCHED, fastmul)
|
||||
ARM_CORE("xscale", xscale, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE, xscale)
|
||||
ARM_CORE("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale)
|
||||
|
||||
/* V5TEJ Architecture Processors */
|
||||
ARM_CORE("arm926ej-s", arm926ejs, 5TEJ, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm1026ej-s", arm1026ejs, 5TEJ, FL_LDSCHED, 9e)
|
||||
|
||||
/* V6 Architecture Processors */
|
||||
ARM_CORE("arm1136j-s", arm1136js, 6J, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm1136jf-s", arm1136jfs, 6J, FL_LDSCHED | FL_VFPV2, 9e)
|
||||
ARM_CORE("arm1176jz-s", arm1176jzs, 6ZK, FL_LDSCHED, 9e)
|
||||
ARM_CORE("arm1176jzf-s", arm1176jzfs, 6ZK, FL_LDSCHED | FL_VFPV2, 9e)
|
||||
ARM_CORE("mpcorenovfp", mpcorenovfp, 6K, FL_LDSCHED, 9e)
|
||||
ARM_CORE("mpcore", mpcore, 6K, FL_LDSCHED | FL_VFPV2, 9e)
|
152
contrib/gcc/config/arm/arm-generic.md
Normal file
152
contrib/gcc/config/arm/arm-generic.md
Normal file
@ -0,0 +1,152 @@
|
||||
;; Generic ARM Pipeline Description
|
||||
;; Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC 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.
|
||||
;;
|
||||
;; GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
;; 02110-1301, USA. */
|
||||
|
||||
(define_automaton "arm")
|
||||
|
||||
;; Write buffer
|
||||
;
|
||||
; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
|
||||
;
|
||||
; The write buffer on some of the arm6 processors is hard to model exactly.
|
||||
; There is room in the buffer for up to two addresses and up to eight words
|
||||
; of memory, but the two needn't be split evenly. When writing the two
|
||||
; addresses are fully pipelined. However, a read from memory that is not
|
||||
; currently in the cache will block until the writes have completed.
|
||||
; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
|
||||
; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
|
||||
; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
|
||||
; cycle to add as well.
|
||||
(define_cpu_unit "write_buf" "arm")
|
||||
|
||||
;; Write blockage unit
|
||||
;
|
||||
; The write_blockage unit models (partially), the fact that reads will stall
|
||||
; until the write buffer empties.
|
||||
; The f_mem_r and r_mem_f could also block, but they are to the stack,
|
||||
; so we don't model them here
|
||||
(define_cpu_unit "write_blockage" "arm")
|
||||
|
||||
;; Core
|
||||
;
|
||||
(define_cpu_unit "core" "arm")
|
||||
|
||||
(define_insn_reservation "r_mem_f_wbuf" 5
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "yes")
|
||||
(eq_attr "type" "r_mem_f")))
|
||||
"core+write_buf*3")
|
||||
|
||||
(define_insn_reservation "store_wbuf" 5
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "yes")
|
||||
(eq_attr "type" "store1")))
|
||||
"core+write_buf*3+write_blockage*5")
|
||||
|
||||
(define_insn_reservation "store2_wbuf" 7
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "yes")
|
||||
(eq_attr "type" "store2")))
|
||||
"core+write_buf*4+write_blockage*7")
|
||||
|
||||
(define_insn_reservation "store3_wbuf" 9
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "yes")
|
||||
(eq_attr "type" "store3")))
|
||||
"core+write_buf*5+write_blockage*9")
|
||||
|
||||
(define_insn_reservation "store4_wbuf" 11
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "yes")
|
||||
(eq_attr "type" "store4")))
|
||||
"core+write_buf*6+write_blockage*11")
|
||||
|
||||
(define_insn_reservation "store2" 3
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "no")
|
||||
(eq_attr "type" "store2")))
|
||||
"core*3")
|
||||
|
||||
(define_insn_reservation "store3" 4
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "no")
|
||||
(eq_attr "type" "store3")))
|
||||
"core*4")
|
||||
|
||||
(define_insn_reservation "store4" 5
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "model_wbuf" "no")
|
||||
(eq_attr "type" "store4")))
|
||||
"core*5")
|
||||
|
||||
(define_insn_reservation "store_ldsched" 1
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "yes")
|
||||
(eq_attr "type" "store1")))
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "load_ldsched_xscale" 3
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "yes")
|
||||
(and (eq_attr "type" "load_byte,load1")
|
||||
(eq_attr "is_xscale" "yes"))))
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "load_ldsched" 2
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "yes")
|
||||
(and (eq_attr "type" "load_byte,load1")
|
||||
(eq_attr "is_xscale" "no"))))
|
||||
"core")
|
||||
|
||||
(define_insn_reservation "load_or_store" 2
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "!yes")
|
||||
(eq_attr "type" "load_byte,load1,load2,load3,load4,store1")))
|
||||
"core*2")
|
||||
|
||||
(define_insn_reservation "mult" 16
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "no") (eq_attr "type" "mult")))
|
||||
"core*16")
|
||||
|
||||
(define_insn_reservation "mult_ldsched_strongarm" 3
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "yes")
|
||||
(and (eq_attr "is_strongarm" "yes")
|
||||
(eq_attr "type" "mult"))))
|
||||
"core*2")
|
||||
|
||||
(define_insn_reservation "mult_ldsched" 4
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "ldsched" "yes")
|
||||
(and (eq_attr "is_strongarm" "no")
|
||||
(eq_attr "type" "mult"))))
|
||||
"core*4")
|
||||
|
||||
(define_insn_reservation "multi_cycle" 32
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(and (eq_attr "core_cycles" "multi")
|
||||
(eq_attr "type" "!mult,load_byte,load1,load2,load3,load4,store1,store2,store3,store4")))
|
||||
"core*32")
|
||||
|
||||
(define_insn_reservation "single_cycle" 1
|
||||
(and (eq_attr "generic_sched" "yes")
|
||||
(eq_attr "core_cycles" "single"))
|
||||
"core")
|
@ -1,5 +1,5 @@
|
||||
/* Definitions of target machine for GNU compiler, for ARM.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
|
||||
and Martin Simmons (@harleqn.co.uk).
|
||||
More major hacks by Richard Earnshaw (rearnsha@arm.com)
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Extended precision floating point.
|
||||
FIXME What format is this? */
|
||||
@ -50,3 +50,11 @@ CC_MODE (CC_DGEU);
|
||||
CC_MODE (CC_DGTU);
|
||||
CC_MODE (CC_C);
|
||||
CC_MODE (CC_N);
|
||||
|
||||
/* Vector modes. */
|
||||
VECTOR_MODES (INT, 4); /* V4QI V2HI */
|
||||
VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
|
||||
VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
|
||||
VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
|
||||
VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Prototypes for exported functions defined in arm.c and pe.c
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Richard Earnshaw (rearnsha@arm.com)
|
||||
Minor hacks by Nick Clifton (nickc@cygnus.com)
|
||||
@ -18,8 +18,8 @@
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||
Boston, MA 02111-1307, USA. */
|
||||
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_ARM_PROTOS_H
|
||||
#define GCC_ARM_PROTOS_H
|
||||
@ -27,76 +27,57 @@
|
||||
extern void arm_override_options (void);
|
||||
extern int use_return_insn (int, rtx);
|
||||
extern int arm_regno_class (int);
|
||||
extern void arm_finalize_pic (int);
|
||||
extern void arm_load_pic_register (unsigned long);
|
||||
extern int arm_volatile_func (void);
|
||||
extern const char *arm_output_epilogue (rtx);
|
||||
extern void arm_expand_prologue (void);
|
||||
extern HOST_WIDE_INT arm_get_frame_size (void);
|
||||
extern const char *arm_strip_name_encoding (const char *);
|
||||
extern void arm_asm_output_labelref (FILE *, const char *);
|
||||
extern unsigned long arm_current_func_type (void);
|
||||
extern unsigned int arm_compute_initial_elimination_offset (unsigned int,
|
||||
unsigned int);
|
||||
extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int,
|
||||
unsigned int);
|
||||
extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
|
||||
unsigned int);
|
||||
extern unsigned int arm_dbx_register_number (unsigned int);
|
||||
extern void arm_output_fn_unwind (FILE *, bool);
|
||||
|
||||
|
||||
#ifdef TREE_CODE
|
||||
extern int arm_return_in_memory (tree);
|
||||
extern void arm_encode_call_attribute (tree, int);
|
||||
#endif
|
||||
#ifdef RTX_CODE
|
||||
extern bool arm_vector_mode_supported_p (enum machine_mode);
|
||||
extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
|
||||
extern int const_ok_for_arm (HOST_WIDE_INT);
|
||||
extern int arm_split_constant (RTX_CODE, enum machine_mode, HOST_WIDE_INT, rtx,
|
||||
rtx, int);
|
||||
extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *);
|
||||
extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
|
||||
HOST_WIDE_INT, rtx, rtx, int);
|
||||
extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
|
||||
rtx *);
|
||||
extern int legitimate_pic_operand_p (rtx);
|
||||
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
|
||||
extern int arm_legitimate_address_p (enum machine_mode, rtx, int);
|
||||
extern rtx legitimize_tls_address (rtx, rtx);
|
||||
extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int);
|
||||
extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
|
||||
extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
|
||||
extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
|
||||
extern int const_double_rtx_ok_for_fpa (rtx);
|
||||
extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
|
||||
extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
|
||||
int);
|
||||
extern int arm_const_double_rtx (rtx);
|
||||
extern int neg_const_double_rtx_ok_for_fpa (rtx);
|
||||
extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
|
||||
bool);
|
||||
extern bool arm_tls_referenced_p (rtx);
|
||||
|
||||
/* Predicates. */
|
||||
extern int s_register_operand (rtx, enum machine_mode);
|
||||
extern int arm_hard_register_operand (rtx, enum machine_mode);
|
||||
extern int f_register_operand (rtx, enum machine_mode);
|
||||
extern int reg_or_int_operand (rtx, enum machine_mode);
|
||||
extern int arm_reload_memory_operand (rtx, enum machine_mode);
|
||||
extern int arm_rhs_operand (rtx, enum machine_mode);
|
||||
extern int arm_rhsm_operand (rtx, enum machine_mode);
|
||||
extern int arm_add_operand (rtx, enum machine_mode);
|
||||
extern int arm_addimm_operand (rtx, enum machine_mode);
|
||||
extern int arm_not_operand (rtx, enum machine_mode);
|
||||
extern int offsettable_memory_operand (rtx, enum machine_mode);
|
||||
extern int alignable_memory_operand (rtx, enum machine_mode);
|
||||
extern int bad_signed_byte_operand (rtx, enum machine_mode);
|
||||
extern int fpa_rhs_operand (rtx, enum machine_mode);
|
||||
extern int fpa_add_operand (rtx, enum machine_mode);
|
||||
extern int power_of_two_operand (rtx, enum machine_mode);
|
||||
extern int nonimmediate_di_operand (rtx, enum machine_mode);
|
||||
extern int di_operand (rtx, enum machine_mode);
|
||||
extern int nonimmediate_soft_df_operand (rtx, enum machine_mode);
|
||||
extern int soft_df_operand (rtx, enum machine_mode);
|
||||
extern int index_operand (rtx, enum machine_mode);
|
||||
extern int const_shift_operand (rtx, enum machine_mode);
|
||||
extern int arm_comparison_operator (rtx, enum machine_mode);
|
||||
extern int shiftable_operator (rtx, enum machine_mode);
|
||||
extern int shift_operator (rtx, enum machine_mode);
|
||||
extern int equality_operator (rtx, enum machine_mode);
|
||||
extern int minmax_operator (rtx, enum machine_mode);
|
||||
extern int cc_register (rtx, enum machine_mode);
|
||||
extern int dominant_cc_register (rtx, enum machine_mode);
|
||||
extern int logical_binary_operator (rtx, enum machine_mode);
|
||||
extern int multi_register_push (rtx, enum machine_mode);
|
||||
extern int load_multiple_operation (rtx, enum machine_mode);
|
||||
extern int store_multiple_operation (rtx, enum machine_mode);
|
||||
extern int cirrus_fp_register (rtx, enum machine_mode);
|
||||
extern int cirrus_general_operand (rtx, enum machine_mode);
|
||||
extern int cirrus_register_operand (rtx, enum machine_mode);
|
||||
extern int cirrus_shift_const (rtx, enum machine_mode);
|
||||
extern int cirrus_memory_offset (rtx);
|
||||
extern int arm_coproc_mem_operand (rtx, bool);
|
||||
extern int arm_no_early_store_addr_dep (rtx, rtx);
|
||||
extern int arm_no_early_alu_shift_dep (rtx, rtx);
|
||||
extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
|
||||
extern int arm_no_early_mul_dep (rtx, rtx);
|
||||
|
||||
extern int tls_mentioned_p (rtx);
|
||||
extern int symbol_mentioned_p (rtx);
|
||||
extern int label_mentioned_p (rtx);
|
||||
extern RTX_CODE minmax_code (rtx);
|
||||
@ -109,8 +90,7 @@ extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
|
||||
rtx, HOST_WIDE_INT *);
|
||||
extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
|
||||
rtx, HOST_WIDE_INT *);
|
||||
extern int arm_gen_movstrqi (rtx *);
|
||||
extern rtx arm_gen_rotated_half_load (rtx);
|
||||
extern int arm_gen_movmemqi (rtx *);
|
||||
extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
|
||||
extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
|
||||
HOST_WIDE_INT);
|
||||
@ -118,6 +98,8 @@ extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
|
||||
extern rtx arm_gen_return_addr_mask (void);
|
||||
extern void arm_reload_in_hi (rtx *);
|
||||
extern void arm_reload_out_hi (rtx *);
|
||||
extern int arm_const_double_inline_cost (rtx);
|
||||
extern bool arm_const_double_by_parts (rtx);
|
||||
extern const char *fp_immediate_constant (rtx);
|
||||
extern const char *output_call (rtx *);
|
||||
extern const char *output_call_mem (rtx *);
|
||||
@ -127,7 +109,6 @@ extern const char *output_mov_long_double_arm_from_arm (rtx *);
|
||||
extern const char *output_mov_double_fpa_from_arm (rtx *);
|
||||
extern const char *output_mov_double_arm_from_fpa (rtx *);
|
||||
extern const char *output_move_double (rtx *);
|
||||
extern const char *output_mov_immediate (rtx *);
|
||||
extern const char *output_add_immediate (rtx *);
|
||||
extern const char *arithmetic_instr (rtx, int);
|
||||
extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
|
||||
@ -141,24 +122,27 @@ extern int arm_debugger_arg_offset (int, rtx);
|
||||
extern int arm_is_longcall_p (rtx, int, int);
|
||||
extern int arm_emit_vector_const (FILE *, rtx);
|
||||
extern const char * arm_output_load_gr (rtx *);
|
||||
extern const char *vfp_output_fstmx (rtx *);
|
||||
extern void arm_set_return_address (rtx, rtx);
|
||||
extern int arm_eliminable_register (rtx);
|
||||
|
||||
extern bool arm_output_addr_const_extra (FILE *, rtx);
|
||||
|
||||
#if defined TREE_CODE
|
||||
extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
|
||||
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
|
||||
extern rtx arm_va_arg (tree, tree);
|
||||
extern int arm_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
|
||||
enum machine_mode, tree, int);
|
||||
extern bool arm_pad_arg_upward (enum machine_mode, tree);
|
||||
extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
|
||||
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
|
||||
extern rtx arm_function_value(tree, tree);
|
||||
#endif
|
||||
extern int arm_apply_result_size (void);
|
||||
|
||||
#if defined AOF_ASSEMBLER
|
||||
#if defined AOF_ASSEMBLER
|
||||
extern rtx aof_pic_entry (rtx);
|
||||
extern char *aof_text_section (void);
|
||||
extern char *aof_data_section (void);
|
||||
extern void aof_add_import (const char *);
|
||||
extern void aof_delete_import (const char *);
|
||||
extern void zero_init_section (void);
|
||||
extern void common_section (void);
|
||||
#endif /* AOF_ASSEMBLER */
|
||||
|
||||
#endif /* RTX_CODE */
|
||||
@ -167,9 +151,7 @@ extern int arm_float_words_big_endian (void);
|
||||
|
||||
/* Thumb functions. */
|
||||
extern void arm_init_expanders (void);
|
||||
extern int thumb_far_jump_used_p (int);
|
||||
extern const char *thumb_unexpanded_epilogue (void);
|
||||
extern HOST_WIDE_INT thumb_get_frame_size (void);
|
||||
extern void thumb_expand_prologue (void);
|
||||
extern void thumb_expand_epilogue (void);
|
||||
#ifdef TREE_CODE
|
||||
@ -180,14 +162,13 @@ extern int thumb_shiftable_const (unsigned HOST_WIDE_INT);
|
||||
extern void thumb_final_prescan_insn (rtx);
|
||||
extern const char *thumb_load_double_from_address (rtx *);
|
||||
extern const char *thumb_output_move_mem_multiple (int, rtx *);
|
||||
extern void thumb_expand_movstrqi (rtx *);
|
||||
extern int thumb_cmp_operand (rtx, enum machine_mode);
|
||||
extern int thumb_cbrch_target_operand (rtx, enum machine_mode);
|
||||
extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
|
||||
extern const char *thumb_call_via_reg (rtx);
|
||||
extern void thumb_expand_movmemqi (rtx *);
|
||||
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
|
||||
extern rtx arm_return_addr (int, rtx);
|
||||
extern void thumb_reload_out_hi (rtx *);
|
||||
extern void thumb_reload_in_hi (rtx *);
|
||||
extern void thumb_set_return_address (rtx, rtx);
|
||||
#endif
|
||||
|
||||
/* Defined in pe.c. */
|
||||
|
5
contrib/gcc/config/arm/arm-tune.md
Normal file
5
contrib/gcc/config/arm/arm-tune.md
Normal file
@ -0,0 +1,5 @@
|
||||
;; -*- buffer-read-only: t -*-
|
||||
;; Generated automatically by gentune.sh from arm-cores.def
|
||||
(define_attr "tune"
|
||||
"arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore"
|
||||
(const (symbol_ref "arm_tune")))
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
155
contrib/gcc/config/arm/arm.opt
Normal file
155
contrib/gcc/config/arm/arm.opt
Normal file
@ -0,0 +1,155 @@
|
||||
; Options for the ARM port of the compiler.
|
||||
|
||||
; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
;
|
||||
; This file is part of GCC.
|
||||
;
|
||||
; GCC 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.
|
||||
;
|
||||
; GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
; 02110-1301, USA.
|
||||
|
||||
mabi=
|
||||
Target RejectNegative Joined Var(target_abi_name)
|
||||
Specify an ABI
|
||||
|
||||
mabort-on-noreturn
|
||||
Target Report Mask(ABORT_NORETURN)
|
||||
Generate a call to abort if a noreturn function returns
|
||||
|
||||
mapcs
|
||||
Target RejectNegative Mask(APCS_FRAME) MaskExists Undocumented
|
||||
|
||||
mapcs-float
|
||||
Target Report Mask(APCS_FLOAT)
|
||||
Pass FP arguments in FP registers
|
||||
|
||||
mapcs-frame
|
||||
Target Report Mask(APCS_FRAME)
|
||||
Generate APCS conformant stack frames
|
||||
|
||||
mapcs-reentrant
|
||||
Target Report Mask(APCS_REENT)
|
||||
Generate re-entrant, PIC code
|
||||
|
||||
mapcs-stack-check
|
||||
Target Report Mask(APCS_STACK) Undocumented
|
||||
|
||||
march=
|
||||
Target RejectNegative Joined
|
||||
Specify the name of the target architecture
|
||||
|
||||
marm
|
||||
Target RejectNegative InverseMask(THUMB) Undocumented
|
||||
|
||||
mbig-endian
|
||||
Target Report RejectNegative Mask(BIG_END)
|
||||
Assume target CPU is configured as big endian
|
||||
|
||||
mcallee-super-interworking
|
||||
Target Report Mask(CALLEE_INTERWORKING)
|
||||
Thumb: Assume non-static functions may be called from ARM code
|
||||
|
||||
mcaller-super-interworking
|
||||
Target Report Mask(CALLER_INTERWORKING)
|
||||
Thumb: Assume function pointers may go to non-Thumb aware code
|
||||
|
||||
mcirrus-fix-invalid-insns
|
||||
Target Report Mask(CIRRUS_FIX_INVALID_INSNS)
|
||||
Cirrus: Place NOPs to avoid invalid instruction combinations
|
||||
|
||||
mcpu=
|
||||
Target RejectNegative Joined
|
||||
Specify the name of the target CPU
|
||||
|
||||
mfloat-abi=
|
||||
Target RejectNegative Joined Var(target_float_abi_name)
|
||||
Specify if floating point hardware should be used
|
||||
|
||||
mfp=
|
||||
Target RejectNegative Joined Undocumented Var(target_fpe_name)
|
||||
|
||||
;; Now ignored.
|
||||
mfpe
|
||||
Target RejectNegative Mask(FPE) Undocumented
|
||||
|
||||
mfpe=
|
||||
Target RejectNegative Joined Undocumented Var(target_fpe_name)
|
||||
|
||||
mfpu=
|
||||
Target RejectNegative Joined Var(target_fpu_name)
|
||||
Specify the name of the target floating point hardware/format
|
||||
|
||||
mhard-float
|
||||
Target RejectNegative
|
||||
Alias for -mfloat-abi=hard
|
||||
|
||||
mlittle-endian
|
||||
Target Report RejectNegative InverseMask(BIG_END)
|
||||
Assume target CPU is configured as little endian
|
||||
|
||||
mlong-calls
|
||||
Target Report Mask(LONG_CALLS)
|
||||
Generate call insns as indirect calls, if necessary
|
||||
|
||||
mpic-register=
|
||||
Target RejectNegative Joined Var(arm_pic_register_string)
|
||||
Specify the register to be used for PIC addressing
|
||||
|
||||
mpoke-function-name
|
||||
Target Report Mask(POKE_FUNCTION_NAME)
|
||||
Store function names in object code
|
||||
|
||||
msched-prolog
|
||||
Target Report Mask(SCHED_PROLOG)
|
||||
Permit scheduling of a function's prologue sequence
|
||||
|
||||
msingle-pic-base
|
||||
Target Report Mask(SINGLE_PIC_BASE)
|
||||
Do not load the PIC register in function prologues
|
||||
|
||||
msoft-float
|
||||
Target RejectNegative
|
||||
Alias for -mfloat-abi=soft
|
||||
|
||||
mstructure-size-boundary=
|
||||
Target RejectNegative Joined Var(structure_size_string)
|
||||
Specify the minimum bit alignment of structures
|
||||
|
||||
mthumb
|
||||
Target Report Mask(THUMB)
|
||||
Compile for the Thumb not the ARM
|
||||
|
||||
mthumb-interwork
|
||||
Target Report Mask(INTERWORK)
|
||||
Support calls between Thumb and ARM instruction sets
|
||||
|
||||
mtp=
|
||||
Target RejectNegative Joined Var(target_thread_switch)
|
||||
Specify how to access the thread pointer
|
||||
|
||||
mtpcs-frame
|
||||
Target Report Mask(TPCS_FRAME)
|
||||
Thumb: Generate (non-leaf) stack frames even if not needed
|
||||
|
||||
mtpcs-leaf-frame
|
||||
Target Report Mask(TPCS_LEAF_FRAME)
|
||||
Thumb: Generate (leaf) stack frames even if not needed
|
||||
|
||||
mtune=
|
||||
Target RejectNegative Joined
|
||||
Tune code for the given processor
|
||||
|
||||
mwords-little-endian
|
||||
Target Report RejectNegative Mask(LITTLE_WORDS)
|
||||
Assume big endian bytes, little endian words
|
388
contrib/gcc/config/arm/arm1020e.md
Normal file
388
contrib/gcc/config/arm/arm1020e.md
Normal file
@ -0,0 +1,388 @@
|
||||
;; ARM 1020E & ARM 1022E Pipeline Description
|
||||
;; Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
;; Contributed by Richard Earnshaw (richard.earnshaw@arm.com)
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC 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.
|
||||
;;
|
||||
;; GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
;; 02110-1301, USA. */
|
||||
|
||||
;; These descriptions are based on the information contained in the
|
||||
;; ARM1020E Technical Reference Manual, Copyright (c) 2003 ARM
|
||||
;; Limited.
|
||||
;;
|
||||
|
||||
;; This automaton provides a pipeline description for the ARM
|
||||
;; 1020E core.
|
||||
;;
|
||||
;; The model given here assumes that the condition for all conditional
|
||||
;; instructions is "true", i.e., that all of the instructions are
|
||||
;; actually executed.
|
||||
|
||||
(define_automaton "arm1020e")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Pipelines
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; There are two pipelines:
|
||||
;;
|
||||
;; - An Arithmetic Logic Unit (ALU) pipeline.
|
||||
;;
|
||||
;; The ALU pipeline has fetch, issue, decode, execute, memory, and
|
||||
;; write stages. We only need to model the execute, memory and write
|
||||
;; stages.
|
||||
;;
|
||||
;; - A Load-Store Unit (LSU) pipeline.
|
||||
;;
|
||||
;; The LSU pipeline has decode, execute, memory, and write stages.
|
||||
;; We only model the execute, memory and write stages.
|
||||
|
||||
(define_cpu_unit "1020a_e,1020a_m,1020a_w" "arm1020e")
|
||||
(define_cpu_unit "1020l_e,1020l_m,1020l_w" "arm1020e")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ALU Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; ALU instructions require three cycles to execute, and use the ALU
|
||||
;; pipeline in each of the three stages. The results are available
|
||||
;; after the execute stage stage has finished.
|
||||
;;
|
||||
;; If the destination register is the PC, the pipelines are stalled
|
||||
;; for several cycles. That case is not modeled here.
|
||||
|
||||
;; ALU operations with no shifted operand
|
||||
(define_insn_reservation "1020alu_op" 1
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "alu"))
|
||||
"1020a_e,1020a_m,1020a_w")
|
||||
|
||||
;; ALU operations with a shift-by-constant operand
|
||||
(define_insn_reservation "1020alu_shift_op" 1
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "alu_shift"))
|
||||
"1020a_e,1020a_m,1020a_w")
|
||||
|
||||
;; ALU operations with a shift-by-register operand
|
||||
;; These really stall in the decoder, in order to read
|
||||
;; the shift value in a second cycle. Pretend we take two cycles in
|
||||
;; the execute stage.
|
||||
(define_insn_reservation "1020alu_shift_reg_op" 2
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "alu_shift_reg"))
|
||||
"1020a_e*2,1020a_m,1020a_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Multiplication Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Multiplication instructions loop in the execute stage until the
|
||||
;; instruction has been passed through the multiplier array enough
|
||||
;; times.
|
||||
|
||||
;; The result of the "smul" and "smulw" instructions is not available
|
||||
;; until after the memory stage.
|
||||
(define_insn_reservation "1020mult1" 2
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "smulxy,smulwy"))
|
||||
"1020a_e,1020a_m,1020a_w")
|
||||
|
||||
;; The "smlaxy" and "smlawx" instructions require two iterations through
|
||||
;; the execute stage; the result is available immediately following
|
||||
;; the execute stage.
|
||||
(define_insn_reservation "1020mult2" 2
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "smlaxy,smlalxy,smlawx"))
|
||||
"1020a_e*2,1020a_m,1020a_w")
|
||||
|
||||
;; The "smlalxy", "mul", and "mla" instructions require two iterations
|
||||
;; through the execute stage; the result is not available until after
|
||||
;; the memory stage.
|
||||
(define_insn_reservation "1020mult3" 3
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "smlalxy,mul,mla"))
|
||||
"1020a_e*2,1020a_m,1020a_w")
|
||||
|
||||
;; The "muls" and "mlas" instructions loop in the execute stage for
|
||||
;; four iterations in order to set the flags. The value result is
|
||||
;; available after three iterations.
|
||||
(define_insn_reservation "1020mult4" 3
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "muls,mlas"))
|
||||
"1020a_e*4,1020a_m,1020a_w")
|
||||
|
||||
;; Long multiply instructions that produce two registers of
|
||||
;; output (such as umull) make their results available in two cycles;
|
||||
;; the least significant word is available before the most significant
|
||||
;; word. That fact is not modeled; instead, the instructions are
|
||||
;; described.as if the entire result was available at the end of the
|
||||
;; cycle in which both words are available.
|
||||
|
||||
;; The "umull", "umlal", "smull", and "smlal" instructions all take
|
||||
;; three iterations through the execute cycle, and make their results
|
||||
;; available after the memory cycle.
|
||||
(define_insn_reservation "1020mult5" 4
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "umull,umlal,smull,smlal"))
|
||||
"1020a_e*3,1020a_m,1020a_w")
|
||||
|
||||
;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
|
||||
;; the execute stage for five iterations in order to set the flags.
|
||||
;; The value result is available after four iterations.
|
||||
(define_insn_reservation "1020mult6" 4
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "insn" "umulls,umlals,smulls,smlals"))
|
||||
"1020a_e*5,1020a_m,1020a_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Load/Store Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The models for load/store instructions do not accurately describe
|
||||
;; the difference between operations with a base register writeback
|
||||
;; (such as "ldm!"). These models assume that all memory references
|
||||
;; hit in dcache.
|
||||
|
||||
;; LSU instructions require six cycles to execute. They use the ALU
|
||||
;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
|
||||
;; three through six.
|
||||
;; Loads and stores which use a scaled register offset or scaled
|
||||
;; register pre-indexed addressing mode take three cycles EXCEPT for
|
||||
;; those that are base + offset with LSL of 0 or 2, or base - offset
|
||||
;; with LSL of zero. The remainder take 1 cycle to execute.
|
||||
;; For 4byte loads there is a bypass from the load stage
|
||||
|
||||
(define_insn_reservation "1020load1_op" 2
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "load_byte,load1"))
|
||||
"1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
(define_insn_reservation "1020store1_op" 0
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "store1"))
|
||||
"1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
;; A load's result can be stored by an immediately following store
|
||||
(define_bypass 1 "1020load1_op" "1020store1_op" "arm_no_early_store_addr_dep")
|
||||
|
||||
;; On a LDM/STM operation, the LSU pipeline iterates until all of the
|
||||
;; registers have been processed.
|
||||
;;
|
||||
;; The time it takes to load the data depends on whether or not the
|
||||
;; base address is 64-bit aligned; if it is not, an additional cycle
|
||||
;; is required. This model assumes that the address is always 64-bit
|
||||
;; aligned. Because the processor can load two registers per cycle,
|
||||
;; that assumption means that we use the same instruction reservations
|
||||
;; for loading 2k and 2k - 1 registers.
|
||||
;;
|
||||
;; The ALU pipeline is decoupled after the first cycle unless there is
|
||||
;; a register dependency; the dependency is cleared as soon as the LDM/STM
|
||||
;; has dealt with the corresponding register. So for example,
|
||||
;; stmia sp, {r0-r3}
|
||||
;; add r0, r0, #4
|
||||
;; will have one fewer stalls than
|
||||
;; stmia sp, {r0-r3}
|
||||
;; add r3, r3, #4
|
||||
;;
|
||||
;; As with ALU operations, if one of the destination registers is the
|
||||
;; PC, there are additional stalls; that is not modeled.
|
||||
|
||||
(define_insn_reservation "1020load2_op" 2
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "load2"))
|
||||
"1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
(define_insn_reservation "1020store2_op" 0
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "store2"))
|
||||
"1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
(define_insn_reservation "1020load34_op" 3
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "load3,load4"))
|
||||
"1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
|
||||
|
||||
(define_insn_reservation "1020store34_op" 0
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "store3,store4"))
|
||||
"1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Branch and Call Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Branch instructions are difficult to model accurately. The ARM
|
||||
;; core can predict most branches. If the branch is predicted
|
||||
;; correctly, and predicted early enough, the branch can be completely
|
||||
;; eliminated from the instruction stream. Some branches can
|
||||
;; therefore appear to require zero cycles to execute. We assume that
|
||||
;; all branches are predicted correctly, and that the latency is
|
||||
;; therefore the minimum value.
|
||||
|
||||
(define_insn_reservation "1020branch_op" 0
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "branch"))
|
||||
"1020a_e")
|
||||
|
||||
;; The latency for a call is not predictable. Therefore, we use 32 as
|
||||
;; roughly equivalent to positive infinity.
|
||||
|
||||
(define_insn_reservation "1020call_op" 32
|
||||
(and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "type" "call"))
|
||||
"1020a_e*32")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; VFP
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define_cpu_unit "v10_fmac" "arm1020e")
|
||||
|
||||
(define_cpu_unit "v10_ds" "arm1020e")
|
||||
|
||||
(define_cpu_unit "v10_fmstat" "arm1020e")
|
||||
|
||||
(define_cpu_unit "v10_ls1,v10_ls2,v10_ls3" "arm1020e")
|
||||
|
||||
;; fmstat is a serializing instruction. It will stall the core until
|
||||
;; the mac and ds units have completed.
|
||||
(exclusion_set "v10_fmac,v10_ds" "v10_fmstat")
|
||||
|
||||
(define_attr "vfp10" "yes,no"
|
||||
(const (if_then_else (and (eq_attr "tune" "arm1020e,arm1022e")
|
||||
(eq_attr "fpu" "vfp"))
|
||||
(const_string "yes") (const_string "no"))))
|
||||
|
||||
;; The VFP "type" attributes differ from those used in the FPA model.
|
||||
;; ffarith Fast floating point insns, e.g. abs, neg, cpy, cmp.
|
||||
;; farith Most arithmetic insns.
|
||||
;; fmul Double precision multiply.
|
||||
;; fdivs Single precision sqrt or division.
|
||||
;; fdivd Double precision sqrt or division.
|
||||
;; f_flag fmstat operation
|
||||
;; f_load Floating point load from memory.
|
||||
;; f_store Floating point store to memory.
|
||||
;; f_2_r Transfer vfp to arm reg.
|
||||
;; r_2_f Transfer arm to vfp reg.
|
||||
|
||||
;; Note, no instruction can issue to the VFP if the core is stalled in the
|
||||
;; first execute state. We model this by using 1020a_e in the first cycle.
|
||||
(define_insn_reservation "v10_ffarith" 5
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "ffarith"))
|
||||
"1020a_e+v10_fmac")
|
||||
|
||||
(define_insn_reservation "v10_farith" 5
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "farith"))
|
||||
"1020a_e+v10_fmac")
|
||||
|
||||
(define_insn_reservation "v10_cvt" 5
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_cvt"))
|
||||
"1020a_e+v10_fmac")
|
||||
|
||||
(define_insn_reservation "v10_fmul" 6
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "fmul"))
|
||||
"1020a_e+v10_fmac*2")
|
||||
|
||||
(define_insn_reservation "v10_fdivs" 18
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "fdivs"))
|
||||
"1020a_e+v10_ds*14")
|
||||
|
||||
(define_insn_reservation "v10_fdivd" 32
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "fdivd"))
|
||||
"1020a_e+v10_fmac+v10_ds*28")
|
||||
|
||||
(define_insn_reservation "v10_floads" 4
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_loads"))
|
||||
"1020a_e+1020l_e+v10_ls1,v10_ls2")
|
||||
|
||||
;; We model a load of a double as needing all the vfp ls* stage in cycle 1.
|
||||
;; This gives the correct mix between single-and double loads where a flds
|
||||
;; followed by and fldd will stall for one cycle, but two back-to-back fldd
|
||||
;; insns stall for two cycles.
|
||||
(define_insn_reservation "v10_floadd" 5
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_loadd"))
|
||||
"1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
|
||||
|
||||
;; Moves to/from arm regs also use the load/store pipeline.
|
||||
|
||||
(define_insn_reservation "v10_c2v" 4
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "r_2_f"))
|
||||
"1020a_e+1020l_e+v10_ls1,v10_ls2")
|
||||
|
||||
(define_insn_reservation "v10_fstores" 1
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_stores"))
|
||||
"1020a_e+1020l_e+v10_ls1,v10_ls2")
|
||||
|
||||
(define_insn_reservation "v10_fstored" 1
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_stored"))
|
||||
"1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
|
||||
|
||||
(define_insn_reservation "v10_v2c" 1
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_2_r"))
|
||||
"1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
(define_insn_reservation "v10_to_cpsr" 2
|
||||
(and (eq_attr "vfp10" "yes")
|
||||
(eq_attr "type" "f_flag"))
|
||||
"1020a_e+v10_fmstat,1020a_e+1020l_e,1020l_m,1020l_w")
|
||||
|
||||
;; VFP bypasses
|
||||
|
||||
;; There are bypasses for most operations other than store
|
||||
|
||||
(define_bypass 3
|
||||
"v10_c2v,v10_floads"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd,v10_cvt")
|
||||
|
||||
(define_bypass 4
|
||||
"v10_floadd"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
|
||||
|
||||
;; Arithmetic to other arithmetic saves a cycle due to forwarding
|
||||
(define_bypass 4
|
||||
"v10_ffarith,v10_farith"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
|
||||
|
||||
(define_bypass 5
|
||||
"v10_fmul"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
|
||||
|
||||
(define_bypass 17
|
||||
"v10_fdivs"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
|
||||
|
||||
(define_bypass 31
|
||||
"v10_fdivd"
|
||||
"v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
|
||||
|
||||
;; VFP anti-dependencies.
|
||||
|
||||
;; There is one anti-dependence in the following case (not yet modelled):
|
||||
;; - After a store: one extra cycle for both fsts and fstd
|
||||
;; Note, back-to-back fstd instructions will overload the load/store datapath
|
||||
;; causing a two-cycle stall.
|
241
contrib/gcc/config/arm/arm1026ejs.md
Normal file
241
contrib/gcc/config/arm/arm1026ejs.md
Normal file
@ -0,0 +1,241 @@
|
||||
;; ARM 1026EJ-S Pipeline Description
|
||||
;; Copyright (C) 2003 Free Software Foundation, Inc.
|
||||
;; Written by CodeSourcery, LLC.
|
||||
;;
|
||||
;; This file is part of GCC.
|
||||
;;
|
||||
;; GCC 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.
|
||||
;;
|
||||
;; GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
;; 02110-1301, USA. */
|
||||
|
||||
;; These descriptions are based on the information contained in the
|
||||
;; ARM1026EJ-S Technical Reference Manual, Copyright (c) 2003 ARM
|
||||
;; Limited.
|
||||
;;
|
||||
|
||||
;; This automaton provides a pipeline description for the ARM
|
||||
;; 1026EJ-S core.
|
||||
;;
|
||||
;; The model given here assumes that the condition for all conditional
|
||||
;; instructions is "true", i.e., that all of the instructions are
|
||||
;; actually executed.
|
||||
|
||||
(define_automaton "arm1026ejs")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Pipelines
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; There are two pipelines:
|
||||
;;
|
||||
;; - An Arithmetic Logic Unit (ALU) pipeline.
|
||||
;;
|
||||
;; The ALU pipeline has fetch, issue, decode, execute, memory, and
|
||||
;; write stages. We only need to model the execute, memory and write
|
||||
;; stages.
|
||||
;;
|
||||
;; - A Load-Store Unit (LSU) pipeline.
|
||||
;;
|
||||
;; The LSU pipeline has decode, execute, memory, and write stages.
|
||||
;; We only model the execute, memory and write stages.
|
||||
|
||||
(define_cpu_unit "a_e,a_m,a_w" "arm1026ejs")
|
||||
(define_cpu_unit "l_e,l_m,l_w" "arm1026ejs")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; ALU Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; ALU instructions require three cycles to execute, and use the ALU
|
||||
;; pipeline in each of the three stages. The results are available
|
||||
;; after the execute stage stage has finished.
|
||||
;;
|
||||
;; If the destination register is the PC, the pipelines are stalled
|
||||
;; for several cycles. That case is not modeled here.
|
||||
|
||||
;; ALU operations with no shifted operand
|
||||
(define_insn_reservation "alu_op" 1
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "alu"))
|
||||
"a_e,a_m,a_w")
|
||||
|
||||
;; ALU operations with a shift-by-constant operand
|
||||
(define_insn_reservation "alu_shift_op" 1
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "alu_shift"))
|
||||
"a_e,a_m,a_w")
|
||||
|
||||
;; ALU operations with a shift-by-register operand
|
||||
;; These really stall in the decoder, in order to read
|
||||
;; the shift value in a second cycle. Pretend we take two cycles in
|
||||
;; the execute stage.
|
||||
(define_insn_reservation "alu_shift_reg_op" 2
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "alu_shift_reg"))
|
||||
"a_e*2,a_m,a_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Multiplication Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Multiplication instructions loop in the execute stage until the
|
||||
;; instruction has been passed through the multiplier array enough
|
||||
;; times.
|
||||
|
||||
;; The result of the "smul" and "smulw" instructions is not available
|
||||
;; until after the memory stage.
|
||||
(define_insn_reservation "mult1" 2
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "smulxy,smulwy"))
|
||||
"a_e,a_m,a_w")
|
||||
|
||||
;; The "smlaxy" and "smlawx" instructions require two iterations through
|
||||
;; the execute stage; the result is available immediately following
|
||||
;; the execute stage.
|
||||
(define_insn_reservation "mult2" 2
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "smlaxy,smlalxy,smlawx"))
|
||||
"a_e*2,a_m,a_w")
|
||||
|
||||
;; The "smlalxy", "mul", and "mla" instructions require two iterations
|
||||
;; through the execute stage; the result is not available until after
|
||||
;; the memory stage.
|
||||
(define_insn_reservation "mult3" 3
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "smlalxy,mul,mla"))
|
||||
"a_e*2,a_m,a_w")
|
||||
|
||||
;; The "muls" and "mlas" instructions loop in the execute stage for
|
||||
;; four iterations in order to set the flags. The value result is
|
||||
;; available after three iterations.
|
||||
(define_insn_reservation "mult4" 3
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "muls,mlas"))
|
||||
"a_e*4,a_m,a_w")
|
||||
|
||||
;; Long multiply instructions that produce two registers of
|
||||
;; output (such as umull) make their results available in two cycles;
|
||||
;; the least significant word is available before the most significant
|
||||
;; word. That fact is not modeled; instead, the instructions are
|
||||
;; described.as if the entire result was available at the end of the
|
||||
;; cycle in which both words are available.
|
||||
|
||||
;; The "umull", "umlal", "smull", and "smlal" instructions all take
|
||||
;; three iterations through the execute cycle, and make their results
|
||||
;; available after the memory cycle.
|
||||
(define_insn_reservation "mult5" 4
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "umull,umlal,smull,smlal"))
|
||||
"a_e*3,a_m,a_w")
|
||||
|
||||
;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
|
||||
;; the execute stage for five iterations in order to set the flags.
|
||||
;; The value result is available after four iterations.
|
||||
(define_insn_reservation "mult6" 4
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "insn" "umulls,umlals,smulls,smlals"))
|
||||
"a_e*5,a_m,a_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Load/Store Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; The models for load/store instructions do not accurately describe
|
||||
;; the difference between operations with a base register writeback
|
||||
;; (such as "ldm!"). These models assume that all memory references
|
||||
;; hit in dcache.
|
||||
|
||||
;; LSU instructions require six cycles to execute. They use the ALU
|
||||
;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
|
||||
;; three through six.
|
||||
;; Loads and stores which use a scaled register offset or scaled
|
||||
;; register pre-indexed addressing mode take three cycles EXCEPT for
|
||||
;; those that are base + offset with LSL of 0 or 2, or base - offset
|
||||
;; with LSL of zero. The remainder take 1 cycle to execute.
|
||||
;; For 4byte loads there is a bypass from the load stage
|
||||
|
||||
(define_insn_reservation "load1_op" 2
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "load_byte,load1"))
|
||||
"a_e+l_e,l_m,a_w+l_w")
|
||||
|
||||
(define_insn_reservation "store1_op" 0
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "store1"))
|
||||
"a_e+l_e,l_m,a_w+l_w")
|
||||
|
||||
;; A load's result can be stored by an immediately following store
|
||||
(define_bypass 1 "load1_op" "store1_op" "arm_no_early_store_addr_dep")
|
||||
|
||||
;; On a LDM/STM operation, the LSU pipeline iterates until all of the
|
||||
;; registers have been processed.
|
||||
;;
|
||||
;; The time it takes to load the data depends on whether or not the
|
||||
;; base address is 64-bit aligned; if it is not, an additional cycle
|
||||
;; is required. This model assumes that the address is always 64-bit
|
||||
;; aligned. Because the processor can load two registers per cycle,
|
||||
;; that assumption means that we use the same instruction reservations
|
||||
;; for loading 2k and 2k - 1 registers.
|
||||
;;
|
||||
;; The ALU pipeline is stalled until the completion of the last memory
|
||||
;; stage in the LSU pipeline. That is modeled by keeping the ALU
|
||||
;; execute stage busy until that point.
|
||||
;;
|
||||
;; As with ALU operations, if one of the destination registers is the
|
||||
;; PC, there are additional stalls; that is not modeled.
|
||||
|
||||
(define_insn_reservation "load2_op" 2
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "load2"))
|
||||
"a_e+l_e,l_m,a_w+l_w")
|
||||
|
||||
(define_insn_reservation "store2_op" 0
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "store2"))
|
||||
"a_e+l_e,l_m,a_w+l_w")
|
||||
|
||||
(define_insn_reservation "load34_op" 3
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "load3,load4"))
|
||||
"a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
|
||||
|
||||
(define_insn_reservation "store34_op" 0
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "store3,store4"))
|
||||
"a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Branch and Call Instructions
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Branch instructions are difficult to model accurately. The ARM
|
||||
;; core can predict most branches. If the branch is predicted
|
||||
;; correctly, and predicted early enough, the branch can be completely
|
||||
;; eliminated from the instruction stream. Some branches can
|
||||
;; therefore appear to require zero cycles to execute. We assume that
|
||||
;; all branches are predicted correctly, and that the latency is
|
||||
;; therefore the minimum value.
|
||||
|
||||
(define_insn_reservation "branch_op" 0
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "branch"))
|
||||
"nothing")
|
||||
|
||||
;; The latency for a call is not predictable. Therefore, we use 32 as
|
||||
;; roughly equivalent to positive infinity.
|
||||
|
||||
(define_insn_reservation "call_op" 32
|
||||
(and (eq_attr "tune" "arm1026ejs")
|
||||
(eq_attr "type" "call"))
|
||||
"nothing")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user