IFC @ r226824

This commit is contained in:
Peter Grehan 2011-10-27 04:56:53 +00:00
commit 70d8f36aa4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/bhyve/; revision=226825
3008 changed files with 162211 additions and 121974 deletions

View File

@ -123,8 +123,6 @@ usr.sbin/zic edwin Heads-up appreciated, since this code is
maintained by a third party source. maintained by a third party source.
lib/libc/stdtime edwin Heads-up appreciated, since parts of this code lib/libc/stdtime edwin Heads-up appreciated, since parts of this code
is maintained by a third party source. is maintained by a third party source.
sysinstall randi Please contact about any major changes so that
they can be co-ordinated.
sbin/routed bms Pre-commit review; notify vendor at rhyolite.com sbin/routed bms Pre-commit review; notify vendor at rhyolite.com
Following are the entries from the Makefiles, and a few other sources. Following are the entries from the Makefiles, and a few other sources.

View File

@ -1018,7 +1018,8 @@ _yacc= usr.bin/yacc
_awk= usr.bin/awk _awk= usr.bin/awk
.endif .endif
.if ${BOOTSTRAPPING} < 700018 .if ${MK_BSNMP} != "no" && \
(${BOOTSTRAPPING} < 700018 || !exists(/usr/sbin/gensnmptree))
_gensnmptree= usr.sbin/bsnmpd/gensnmptree _gensnmptree= usr.sbin/bsnmpd/gensnmptree
.endif .endif
@ -1030,7 +1031,9 @@ _crunchgen= usr.sbin/crunch/crunchgen
.if ${MK_CLANG} != "no" .if ${MK_CLANG} != "no"
_clang_tblgen= \ _clang_tblgen= \
lib/clang/libllvmsupport \ lib/clang/libllvmsupport \
usr.bin/clang/tblgen lib/clang/libllvmtablegen \
usr.bin/clang/tblgen \
usr.bin/clang/clang-tblgen
.endif .endif
.if ${MK_CDDL} != "no" && \ .if ${MK_CDDL} != "no" && \
@ -1106,7 +1109,6 @@ build-tools:
${_aicasm} \ ${_aicasm} \
usr.bin/awk \ usr.bin/awk \
lib/libmagic \ lib/libmagic \
usr.sbin/sysinstall \
usr.bin/mkesdb_static \ usr.bin/mkesdb_static \
usr.bin/mkcsmapper_static usr.bin/mkcsmapper_static
${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \ ${_+_}@${ECHODIR} "===> ${_tool} (obj,build-tools)"; \
@ -1218,7 +1220,8 @@ _startup_libs+= lib/libc
gnu/lib/libgcc__L: lib/libc__L gnu/lib/libgcc__L: lib/libc__L
_prebuild_libs= ${_kerberos5_lib_libasn1} ${_kerberos5_lib_libheimntlm} \ _prebuild_libs= ${_kerberos5_lib_libasn1} ${_kerberos5_lib_libhdb} \
${_kerberos5_lib_libheimntlm} \
${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \ ${_kerberos5_lib_libhx509} ${_kerberos5_lib_libkrb5} \
${_kerberos5_lib_libroken} \ ${_kerberos5_lib_libroken} \
lib/libbz2 lib/libcom_err lib/libcrypt \ lib/libbz2 lib/libcom_err lib/libcrypt \
@ -1268,6 +1271,19 @@ secure/lib/libssh__L: lib/libgssapi__L kerberos5/lib/libkrb5__L \
_secure_lib= secure/lib _secure_lib= secure/lib
.endif .endif
.if ${MK_KERBEROS} != "no"
kerberos5/lib/libasn1__L: lib/libcom_err__L kerberos5/lib/libroken__L
kerberos5/lib/libhdb__L: kerberos5/lib/libasn1__L lib/libcom_err__L \
kerberos5/lib/libkrb5__L kerberos5/lib/libroken__L
kerberos5/lib/libheimntlm__L: secure/lib/libcrypto__L kerberos5/lib/libkrb5__L
kerberos5/lib/libhx509__L: kerberos5/lib/libasn1__L lib/libcom_err__L \
secure/lib/libcrypto__L kerberos5/lib/libroken__L
kerberos5/lib/libkrb5__L: kerberos5/lib/libasn1__L lib/libcom_err__L \
lib/libcrypt__L secure/lib/libcrypto__L kerberos5/lib/libhx509__L \
kerberos5/lib/libroken__L
kerberos5/lib/libroken__L: lib/libcrypt__L
.endif
.if ${MK_GSSAPI} != "no" .if ${MK_GSSAPI} != "no"
_lib_libgssapi= lib/libgssapi _lib_libgssapi= lib/libgssapi
.endif .endif
@ -1279,6 +1295,7 @@ _lib_libipx= lib/libipx
.if ${MK_KERBEROS} != "no" .if ${MK_KERBEROS} != "no"
_kerberos5_lib= kerberos5/lib _kerberos5_lib= kerberos5/lib
_kerberos5_lib_libasn1= kerberos5/lib/libasn1 _kerberos5_lib_libasn1= kerberos5/lib/libasn1
_kerberos5_lib_libhdb= kerberos5/lib/libhdb
_kerberos5_lib_libkrb5= kerberos5/lib/libkrb5 _kerberos5_lib_libkrb5= kerberos5/lib/libkrb5
_kerberos5_lib_libhx509= kerberos5/lib/libhx509 _kerberos5_lib_libhx509= kerberos5/lib/libhx509
_kerberos5_lib_libroken= kerberos5/lib/libroken _kerberos5_lib_libroken= kerberos5/lib/libroken

View File

@ -38,6 +38,19 @@
# xargs -n1 | sort | uniq -d; # xargs -n1 | sort | uniq -d;
# done # done
# 20110930: sysinstall removed
OLD_FILES+=usr/sbin/sysinstall
OLD_FILES+=usr/share/man/man8/sysinstall.8.gz
OLD_FILES+=usr/lib/libftpio.a
OLD_FILES+=usr/lib/libftpio.so
OLD_LIBS+=usr/lib/libftpio.so.8
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_FILES+=usr/lib32/libftpio.a
OLD_FILES+=usr/lib32/libftpio.so
OLD_LIBS+=usr/lib32/libftpio.so.8
.endif
OLD_FILES+=usr/include/ftpio.h
OLD_FILES+=usr/share/man/man3/ftpio.3.gz
# 20110915: rename congestion control manpages # 20110915: rename congestion control manpages
OLD_FILES+=usr/share/man/man4/cc.4.gz OLD_FILES+=usr/share/man/man4/cc.4.gz
OLD_FILES+=usr/share/man/man9/cc.9.gz OLD_FILES+=usr/share/man/man9/cc.9.gz
@ -54,7 +67,7 @@ OLD_LIBS+=usr/lib/libdwarf.so.2
OLD_LIBS+=usr/lib/libopie.so.6 OLD_LIBS+=usr/lib/libopie.so.6
OLD_LIBS+=usr/lib/librtld_db.so.1 OLD_LIBS+=usr/lib/librtld_db.so.1
OLD_LIBS+=usr/lib/libtacplus.so.4 OLD_LIBS+=usr/lib/libtacplus.so.4
.if ${TARGET_ARCH} == "amd64" .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_LIBS+=usr/lib32/libcam.so.5 OLD_LIBS+=usr/lib32/libcam.so.5
OLD_LIBS+=usr/lib32/libpcap.so.7 OLD_LIBS+=usr/lib32/libpcap.so.7
OLD_LIBS+=usr/lib32/libufs.so.5 OLD_LIBS+=usr/lib32/libufs.so.5
@ -92,7 +105,7 @@ OLD_FILES+=usr/lib/libpkg.a
OLD_FILES+=usr/lib/libpkg.so OLD_FILES+=usr/lib/libpkg.so
OLD_LIBS+=usr/lib/libpkg.so.0 OLD_LIBS+=usr/lib/libpkg.so.0
OLD_FILES+=usr/lib/libpkg_p.a OLD_FILES+=usr/lib/libpkg_p.a
.if ${TARGET_ARCH} == "amd64" .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_FILES+=usr/lib32/libpkg.a OLD_FILES+=usr/lib32/libpkg.a
OLD_FILES+=usr/lib32/libpkg.so OLD_FILES+=usr/lib32/libpkg.so
OLD_LIBS+=usr/lib32/libpkg.so.0 OLD_LIBS+=usr/lib32/libpkg.so.0
@ -100,7 +113,7 @@ OLD_FILES+=usr/lib32/libpkg_p.a
.endif .endif
# 20110517: libsbuf version bump # 20110517: libsbuf version bump
OLD_LIBS+=lib/libsbuf.so.5 OLD_LIBS+=lib/libsbuf.so.5
.if ${TARGET_ARCH} == "amd64" .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_LIBS+=usr/lib32/libsbuf.so.5 OLD_LIBS+=usr/lib32/libsbuf.so.5
.endif .endif
# 20110502: new clang import which bumps version from 2.9 to 3.0 # 20110502: new clang import which bumps version from 2.9 to 3.0
@ -131,7 +144,7 @@ OLD_FILES+=usr/lib/libobjc_p.a
OLD_FILES+=usr/libexec/cc1obj OLD_FILES+=usr/libexec/cc1obj
OLD_LIBS+=usr/lib/libobjc.so.4 OLD_LIBS+=usr/lib/libobjc.so.4
OLD_DIRS+=usr/include/objc OLD_DIRS+=usr/include/objc
.if ${TARGET_ARCH} == "amd64" .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_FILES+=usr/lib32/libobjc.a OLD_FILES+=usr/lib32/libobjc.a
OLD_FILES+=usr/lib32/libobjc.so OLD_FILES+=usr/lib32/libobjc.so
OLD_FILES+=usr/lib32/libobjc_p.a OLD_FILES+=usr/lib32/libobjc_p.a
@ -258,7 +271,7 @@ OLD_FILES+=usr/include/machine/intr.h
.endif .endif
# 20100514: library version bump for versioned symbols for liblzma # 20100514: library version bump for versioned symbols for liblzma
OLD_LIBS+=usr/lib/liblzma.so.0 OLD_LIBS+=usr/lib/liblzma.so.0
.if ${TARGET_ARCH} == "amd64" .if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "powerpc64"
OLD_LIBS+=usr/lib32/liblzma.so.0 OLD_LIBS+=usr/lib32/liblzma.so.0
.endif .endif
# 20100511: move GCC-specific headers to /usr/include/gcc # 20100511: move GCC-specific headers to /usr/include/gcc
@ -2580,7 +2593,7 @@ OLD_FILES+=usr/lib/libpam_ssh.a
OLD_FILES+=usr/lib/libpam_ssh_p.a OLD_FILES+=usr/lib/libpam_ssh_p.a
OLD_FILES+=usr/bin/help OLD_FILES+=usr/bin/help
OLD_FILES+=usr/bin/sccs OLD_FILES+=usr/bin/sccs
.if ${TARGET_ARCH} != "amd64" && ${TARGET_ARCH} != "arm" && ${TARGET_ARCH} != "i386" && ${TARGET_ARCH} != "powerpc" .if ${TARGET_ARCH} != "amd64" && ${TARGET} != "arm" && ${TARGET_ARCH} != "i386" && ${TARGET} != "powerpc"
OLD_FILES+=usr/bin/gdbserver OLD_FILES+=usr/bin/gdbserver
.endif .endif
OLD_FILES+=usr/bin/ssh-keysign OLD_FILES+=usr/bin/ssh-keysign

View File

@ -9,8 +9,8 @@ handbook.
Items affecting the ports and packages system can be found in Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before running portupgrade. /usr/ports/UPDATING. Please read that file before running portupgrade.
NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW: NOTE TO PEOPLE WHO THINK THAT FreeBSD 10.x IS SLOW:
FreeBSD 9.x has many debugging features turned on, in both the kernel FreeBSD 10.x has many debugging features turned on, in both the kernel
and userland. These features attempt to detect incorrect use of and userland. These features attempt to detect incorrect use of
system primitives, and encourage loud failure through extra sanity system primitives, and encourage loud failure through extra sanity
checking and fail stop semantics. They also substantially impact checking and fail stop semantics. They also substantially impact
@ -22,6 +22,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
machines to maximize performance. (To disable malloc debugging, run machines to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.) ln -s aj /etc/malloc.conf.)
20110930:
sysinstall has been removed
20110923:
The stable/9 branch created in subversion. This corresponds to the
RELENG_9 branch in CVS.
20110913: 20110913:
This commit modifies vfs_register() so that it uses a hash This commit modifies vfs_register() so that it uses a hash
calculation to set vfc_typenum, which is enabled by default. calculation to set vfc_typenum, which is enabled by default.
@ -455,7 +462,7 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
There's one kernel module for each firmware. Adding "device iwnfw" There's one kernel module for each firmware. Adding "device iwnfw"
to the kernel configuration file means including all three firmware to the kernel configuration file means including all three firmware
images inside the kernel. If you want to include just the one for images inside the kernel. If you want to include just the one for
your wireless card, use the the devices iwn4965fw, iwn5000fw or your wireless card, use the devices iwn4965fw, iwn5000fw or
iwn5150fw. iwn5150fw.
20090926: 20090926:

View File

@ -29,7 +29,7 @@
.\" @(#)df.1 8.3 (Berkeley) 5/8/95 .\" @(#)df.1 8.3 (Berkeley) 5/8/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd November 23, 2008 .Dd October 18, 2011
.Dt DF 1 .Dt DF 1
.Os .Os
.Sh NAME .Sh NAME
@ -63,6 +63,7 @@ The following options are available:
Show all mount points, including those that were mounted with the Show all mount points, including those that were mounted with the
.Dv MNT_IGNORE .Dv MNT_IGNORE
flag. flag.
This is implied for file systems specified on the command line.
.It Fl b .It Fl b
Use 512-byte blocks rather than the default. Use 512-byte blocks rather than the default.
Note that Note that

View File

@ -107,7 +107,7 @@ main(int argc, char *argv[])
const char *fstype; const char *fstype;
char *mntpath, *mntpt; char *mntpath, *mntpt;
const char **vfslist; const char **vfslist;
size_t i, mntsize; int i, mntsize;
int ch, rv; int ch, rv;
fstype = "ufs"; fstype = "ufs";
@ -187,30 +187,21 @@ main(int argc, char *argv[])
argc -= optind; argc -= optind;
argv += optind; argv += optind;
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
bzero(&maxwidths, sizeof(maxwidths));
for (i = 0; i < mntsize; i++)
update_maxwidths(&maxwidths, &mntbuf[i]);
rv = 0; rv = 0;
if (!*argv) { if (!*argv) {
/* everything (modulo -t) */
mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); mntsize = regetmntinfo(&mntbuf, mntsize, vfslist);
bzero(&maxwidths, sizeof(maxwidths)); } else {
for (i = 0; i < mntsize; i++) { /* just the filesystems specified on the command line */
if (cflag) mntbuf = malloc(argc * sizeof(*mntbuf));
addstat(&totalbuf, &mntbuf[i]); if (mntbuf == 0)
update_maxwidths(&maxwidths, &mntbuf[i]); err(1, "malloc()");
} mntsize = 0;
if (cflag) /* continued in for loop below */
update_maxwidths(&maxwidths, &totalbuf);
for (i = 0; i < mntsize; i++)
if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
prtstat(&mntbuf[i], &maxwidths);
if (cflag)
prtstat(&totalbuf, &maxwidths);
exit(rv);
} }
/* iterate through specified filesystems */
for (; *argv; argv++) { for (; *argv; argv++) {
if (stat(*argv, &stbuf) < 0) { if (stat(*argv, &stbuf) < 0) {
if ((mntpt = getmntpt(*argv)) == 0) { if ((mntpt = getmntpt(*argv)) == 0) {
@ -279,14 +270,24 @@ main(int argc, char *argv[])
continue; continue;
} }
if (argc == 1) { /* the user asked for it, so ignore the ignore flag */
bzero(&maxwidths, sizeof(maxwidths)); statfsbuf.f_flags &= ~MNT_IGNORE;
update_maxwidths(&maxwidths, &statfsbuf);
} /* add to list */
prtstat(&statfsbuf, &maxwidths); mntbuf[mntsize++] = statfsbuf;
if (cflag)
addstat(&totalbuf, &statfsbuf);
} }
bzero(&maxwidths, sizeof(maxwidths));
for (i = 0; i < mntsize; i++) {
if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0) {
update_maxwidths(&maxwidths, &mntbuf[i]);
if (cflag)
addstat(&totalbuf, &mntbuf[i]);
}
}
for (i = 0; i < mntsize; i++)
if (aflag || (mntbuf[i].f_flags & MNT_IGNORE) == 0)
prtstat(&mntbuf[i], &maxwidths);
if (cflag) if (cflag)
prtstat(&totalbuf, &maxwidths); prtstat(&totalbuf, &maxwidths);
return (rv); return (rv);

View File

@ -32,7 +32,7 @@
.\" @(#)ls.1 8.7 (Berkeley) 7/29/94 .\" @(#)ls.1 8.7 (Berkeley) 7/29/94
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd April 4, 2008 .Dd September 28, 2011
.Dt LS 1 .Dt LS 1
.Os .Os
.Sh NAME .Sh NAME
@ -357,8 +357,7 @@ option is given,
the numeric ID's are displayed. the numeric ID's are displayed.
.Pp .Pp
If the file is a character special or block special file, If the file is a character special or block special file,
the major and minor device numbers for the file are displayed the device number for the file is displayed in the size field.
in the size field.
If the file is a symbolic link the pathname of the If the file is a symbolic link the pathname of the
linked-to file is preceded by linked-to file is preceded by
.Dq Li -> . .Dq Li -> .

View File

@ -44,7 +44,7 @@ static char sccsid[] = "@(#)ls.c 8.5 (Berkeley) 4/2/94";
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/types.h> #include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mac.h> #include <sys/mac.h>
@ -414,8 +414,8 @@ main(int argc, char *argv[])
fts_options |= FTS_WHITEOUT; fts_options |= FTS_WHITEOUT;
#endif #endif
/* If -l or -s, figure out block size. */ /* If -i, -l or -s, figure out block size. */
if (f_longform || f_size) { if (f_inode || f_longform || f_size) {
if (f_kblocks) if (f_kblocks)
blocksize = 2; blocksize = 2;
else { else {
@ -563,7 +563,7 @@ display(const FTSENT *p, FTSENT *list, int options)
long maxblock; long maxblock;
u_long btotal, labelstrlen, maxinode, maxlen, maxnlink; u_long btotal, labelstrlen, maxinode, maxlen, maxnlink;
u_long maxlabelstr; u_long maxlabelstr;
u_int devstrlen; u_int sizelen;
int maxflags; int maxflags;
gid_t maxgroup; gid_t maxgroup;
uid_t maxuser; uid_t maxuser;
@ -572,7 +572,6 @@ display(const FTSENT *p, FTSENT *list, int options)
int entries, needstats; int entries, needstats;
const char *user, *group; const char *user, *group;
char *flags, *labelstr = NULL; char *flags, *labelstr = NULL;
char buf[STRBUF_SIZEOF(u_quad_t) + 1];
char ngroup[STRBUF_SIZEOF(uid_t) + 1]; char ngroup[STRBUF_SIZEOF(uid_t) + 1];
char nuser[STRBUF_SIZEOF(gid_t) + 1]; char nuser[STRBUF_SIZEOF(gid_t) + 1];
@ -656,7 +655,8 @@ display(const FTSENT *p, FTSENT *list, int options)
MAKENINES(maxsize); MAKENINES(maxsize);
free(jinitmax); free(jinitmax);
} }
devstrlen = 0; d.s_size = 0;
sizelen = 0;
flags = NULL; flags = NULL;
for (cur = list, entries = 0; cur; cur = cur->fts_link) { for (cur = list, entries = 0; cur; cur = cur->fts_link) {
if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
@ -796,14 +796,12 @@ display(const FTSENT *p, FTSENT *list, int options)
np->group = &np->data[ulen + 1]; np->group = &np->data[ulen + 1];
(void)strcpy(np->group, group); (void)strcpy(np->group, group);
if ((S_ISCHR(sp->st_mode) || if (S_ISCHR(sp->st_mode) ||
S_ISBLK(sp->st_mode)) && S_ISBLK(sp->st_mode)) {
devstrlen < DEVSTR_HEX_LEN) { sizelen = snprintf(NULL, 0,
if (minor(sp->st_rdev) > 255 || "%#jx", (uintmax_t)sp->st_rdev);
minor(sp->st_rdev) < 0) if (d.s_size < sizelen)
devstrlen = DEVSTR_HEX_LEN; d.s_size = sizelen;
else
devstrlen = DEVSTR_LEN;
} }
if (f_flags) { if (f_flags) {
@ -837,23 +835,16 @@ display(const FTSENT *p, FTSENT *list, int options)
d.maxlen = maxlen; d.maxlen = maxlen;
if (needstats) { if (needstats) {
d.btotal = btotal; d.btotal = btotal;
(void)snprintf(buf, sizeof(buf), "%lu", maxblock); d.s_block = snprintf(NULL, 0, "%lu", howmany(maxblock, blocksize));
d.s_block = strlen(buf);
d.s_flags = maxflags; d.s_flags = maxflags;
d.s_label = maxlabelstr; d.s_label = maxlabelstr;
d.s_group = maxgroup; d.s_group = maxgroup;
(void)snprintf(buf, sizeof(buf), "%lu", maxinode); d.s_inode = snprintf(NULL, 0, "%lu", maxinode);
d.s_inode = strlen(buf); d.s_nlink = snprintf(NULL, 0, "%lu", maxnlink);
(void)snprintf(buf, sizeof(buf), "%lu", maxnlink); sizelen = f_humanval ? HUMANVALSTR_LEN :
d.s_nlink = strlen(buf); snprintf(NULL, 0, "%ju", maxsize);
if (f_humanval) if (d.s_size < sizelen)
d.s_size = HUMANVALSTR_LEN; d.s_size = sizelen;
else {
(void)snprintf(buf, sizeof(buf), "%ju", maxsize);
d.s_size = strlen(buf);
}
if (d.s_size < devstrlen)
d.s_size = devstrlen;
d.s_user = maxuser; d.s_user = maxuser;
} }
printfcn(&d); printfcn(&d);

View File

@ -36,8 +36,6 @@
#define NO_PRINT 1 #define NO_PRINT 1
#define HUMANVALSTR_LEN 5 #define HUMANVALSTR_LEN 5
#define DEVSTR_LEN 8
#define DEVSTR_HEX_LEN 15
extern long blocksize; /* block size units */ extern long blocksize; /* block size units */

View File

@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
#include <langinfo.h> #include <langinfo.h>
#include <libutil.h> #include <libutil.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@ -351,16 +352,8 @@ printaname(const FTSENT *p, u_long inodefield, u_long sizefield)
static void static void
printdev(size_t width, dev_t dev) printdev(size_t width, dev_t dev)
{ {
char buf[DEVSTR_HEX_LEN + 1];
if (minor(dev) > 255 || minor(dev) < 0) (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev);
(void)snprintf(buf, sizeof(buf), "%3d, 0x%08x",
major(dev), (u_int)minor(dev));
else
(void)snprintf(buf, sizeof(buf), "%3d, %3d",
major(dev), minor(dev));
(void)printf("%*s ", (u_int)width, buf);
} }
static void static void

View File

@ -260,40 +260,34 @@ static int
fastcopy(const char *from, const char *to, struct stat *sbp) fastcopy(const char *from, const char *to, struct stat *sbp)
{ {
struct timeval tval[2]; struct timeval tval[2];
static u_int blen; static u_int blen = MAXPHYS;
static char *bp; static char *bp = NULL;
mode_t oldmode; mode_t oldmode;
int nread, from_fd, to_fd; int nread, from_fd, to_fd;
if ((from_fd = open(from, O_RDONLY, 0)) < 0) { if ((from_fd = open(from, O_RDONLY, 0)) < 0) {
warn("%s", from); warn("fastcopy: open() failed (from): %s", from);
return (1); return (1);
} }
if (blen < sbp->st_blksize) { if (bp == NULL && (bp = malloc((size_t)blen)) == NULL) {
if (bp != NULL) warnx("malloc(%u) failed", blen);
free(bp); return (1);
if ((bp = malloc((size_t)sbp->st_blksize)) == NULL) {
blen = 0;
warnx("malloc failed");
return (1);
}
blen = sbp->st_blksize;
} }
while ((to_fd = while ((to_fd =
open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) { open(to, O_CREAT | O_EXCL | O_TRUNC | O_WRONLY, 0)) < 0) {
if (errno == EEXIST && unlink(to) == 0) if (errno == EEXIST && unlink(to) == 0)
continue; continue;
warn("%s", to); warn("fastcopy: open() failed (to): %s", to);
(void)close(from_fd); (void)close(from_fd);
return (1); return (1);
} }
while ((nread = read(from_fd, bp, (size_t)blen)) > 0) while ((nread = read(from_fd, bp, (size_t)blen)) > 0)
if (write(to_fd, bp, (size_t)nread) != nread) { if (write(to_fd, bp, (size_t)nread) != nread) {
warn("%s", to); warn("fastcopy: write() failed: %s", to);
goto err; goto err;
} }
if (nread < 0) { if (nread < 0) {
warn("%s", from); warn("fastcopy: read() failed: %s", from);
err: if (unlink(to)) err: if (unlink(to))
warn("%s: remove", to); warn("%s: remove", to);
(void)close(from_fd); (void)close(from_fd);

View File

@ -39,63 +39,52 @@ extern fixpt_t ccpu;
extern int cflag, eval, fscale, nlistread, rawcpu; extern int cflag, eval, fscale, nlistread, rawcpu;
extern unsigned long mempages; extern unsigned long mempages;
extern time_t now; extern time_t now;
extern int showthreads, sumrusage, termwidth, totwidth; extern int showthreads, sumrusage, termwidth;
extern STAILQ_HEAD(velisthead, varent) varlist; extern STAILQ_HEAD(velisthead, varent) varlist;
__BEGIN_DECLS __BEGIN_DECLS
void arguments(KINFO *, VARENT *); char *arguments(KINFO *, VARENT *);
void command(KINFO *, VARENT *); char *command(KINFO *, VARENT *);
void cputime(KINFO *, VARENT *); char *cputime(KINFO *, VARENT *);
int donlist(void); int donlist(void);
void elapsed(KINFO *, VARENT *); char *elapsed(KINFO *, VARENT *);
void elapseds(KINFO *, VARENT *); char *elapseds(KINFO *, VARENT *);
void emulname(KINFO *, VARENT *); char *emulname(KINFO *, VARENT *);
VARENT *find_varentry(VAR *); VARENT *find_varentry(VAR *);
const char *fmt_argv(char **, char *, size_t); const char *fmt_argv(char **, char *, size_t);
double getpcpu(const KINFO *); double getpcpu(const KINFO *);
void kvar(KINFO *, VARENT *); char *kvar(KINFO *, VARENT *);
void label(KINFO *, VARENT *); char *label(KINFO *, VARENT *);
void loginclass(KINFO *, VARENT *); char *loginclass(KINFO *, VARENT *);
void logname(KINFO *, VARENT *); char *logname(KINFO *, VARENT *);
void longtname(KINFO *, VARENT *); char *longtname(KINFO *, VARENT *);
void lstarted(KINFO *, VARENT *); char *lstarted(KINFO *, VARENT *);
void maxrss(KINFO *, VARENT *); char *maxrss(KINFO *, VARENT *);
void lockname(KINFO *, VARENT *); char *lockname(KINFO *, VARENT *);
void mwchan(KINFO *, VARENT *); char *mwchan(KINFO *, VARENT *);
void nwchan(KINFO *, VARENT *); char *nwchan(KINFO *, VARENT *);
void pagein(KINFO *, VARENT *); char *pagein(KINFO *, VARENT *);
void parsefmt(const char *, int); void parsefmt(const char *, int);
void pcpu(KINFO *, VARENT *); char *pcpu(KINFO *, VARENT *);
void pmem(KINFO *, VARENT *); char *pmem(KINFO *, VARENT *);
void pri(KINFO *, VARENT *); char *pri(KINFO *, VARENT *);
void printheader(void); void printheader(void);
void priorityr(KINFO *, VARENT *); char *priorityr(KINFO *, VARENT *);
void egroupname(KINFO *, VARENT *); char *egroupname(KINFO *, VARENT *);
void rgroupname(KINFO *, VARENT *); char *rgroupname(KINFO *, VARENT *);
void runame(KINFO *, VARENT *); char *runame(KINFO *, VARENT *);
void rvar(KINFO *, VARENT *); char *rvar(KINFO *, VARENT *);
int s_comm(KINFO *);
int s_cputime(KINFO *);
int s_label(KINFO *);
int s_loginclass(KINFO *);
int s_logname(KINFO *);
int s_egroupname(KINFO *);
int s_rgroupname(KINFO *);
int s_runame(KINFO *);
int s_systime(KINFO *);
int s_uname(KINFO *);
int s_usertime(KINFO *);
void showkey(void); void showkey(void);
void started(KINFO *, VARENT *); char *started(KINFO *, VARENT *);
void state(KINFO *, VARENT *); char *state(KINFO *, VARENT *);
void systime(KINFO *, VARENT *); char *systime(KINFO *, VARENT *);
void tdev(KINFO *, VARENT *); char *tdev(KINFO *, VARENT *);
void tdnam(KINFO *, VARENT *); char *tdnam(KINFO *, VARENT *);
void tname(KINFO *, VARENT *); char *tname(KINFO *, VARENT *);
void ucomm(KINFO *, VARENT *); char *ucomm(KINFO *, VARENT *);
void uname(KINFO *, VARENT *); char *uname(KINFO *, VARENT *);
void upr(KINFO *, VARENT *); char *upr(KINFO *, VARENT *);
void usertime(KINFO *, VARENT *); char *usertime(KINFO *, VARENT *);
void vsize(KINFO *, VARENT *); char *vsize(KINFO *, VARENT *);
void wchan(KINFO *, VARENT *); char *wchan(KINFO *, VARENT *);
__END_DECLS __END_DECLS

View File

@ -57,178 +57,116 @@ static int vcmp(const void *, const void *);
#define KOFF(x) offsetof(struct kinfo_proc, x) #define KOFF(x) offsetof(struct kinfo_proc, x)
#define ROFF(x) offsetof(struct rusage, x) #define ROFF(x) offsetof(struct rusage, x)
#define EMULLEN 13 /* enough for "FreeBSD ELF32" */
#define LWPFMT "d" #define LWPFMT "d"
#define LWPLEN 6
#define NLWPFMT "d" #define NLWPFMT "d"
#define NLWPLEN 4
#define UIDFMT "u" #define UIDFMT "u"
#define UIDLEN 5
#define PIDFMT "d" #define PIDFMT "d"
#define PIDLEN 5
#define USERLEN (MAXLOGNAME - 1)
/* PLEASE KEEP THE TABLE BELOW SORTED ALPHABETICALLY!!! */ /* PLEASE KEEP THE TABLE BELOW SORTED ALPHABETICALLY!!! */
static VAR var[] = { static VAR var[] = {
{"%cpu", "%CPU", NULL, 0, pcpu, NULL, 5, 0, CHAR, NULL, 0}, {"%cpu", "%CPU", NULL, 0, pcpu, 0, CHAR, NULL, 0},
{"%mem", "%MEM", NULL, 0, pmem, NULL, 4, 0, CHAR, NULL, 0}, {"%mem", "%MEM", NULL, 0, pmem, 0, CHAR, NULL, 0},
{"acflag", "ACFLG", NULL, 0, kvar, NULL, 3, KOFF(ki_acflag), USHORT, {"acflag", "ACFLG", NULL, 0, kvar, KOFF(ki_acflag), USHORT, "x", 0},
"x", 0}, {"acflg", "", "acflag", 0, NULL, 0, CHAR, NULL, 0},
{"acflg", "", "acflag", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"args", "COMMAND", NULL, COMM|LJUST|USER, arguments, 0,
{"args", "COMMAND", NULL, COMM|LJUST|USER, arguments, NULL, 16, 0,
CHAR, NULL, 0}, CHAR, NULL, 0},
{"blocked", "", "sigmask", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"blocked", "", "sigmask", 0, NULL, 0, CHAR, NULL, 0},
{"caught", "", "sigcatch", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"caught", "", "sigcatch", 0, NULL, 0, CHAR, NULL, 0},
{"class", "CLASS", NULL, LJUST, loginclass, s_loginclass, {"class", "CLASS", NULL, LJUST, loginclass, 0, CHAR, NULL, 0},
MAXLOGNAME-1, 0, CHAR, NULL, 0}, {"comm", "COMMAND", NULL, LJUST, ucomm, 0, CHAR, NULL, 0},
{"comm", "COMMAND", NULL, LJUST, ucomm, s_comm, {"command", "COMMAND", NULL, COMM|LJUST|USER, command, 0,
COMMLEN + TDNAMLEN + 1, 0, CHAR, NULL, 0},
{"command", "COMMAND", NULL, COMM|LJUST|USER, command, NULL, 16, 0,
CHAR, NULL, 0}, CHAR, NULL, 0},
{"cpu", "CPU", NULL, 0, kvar, NULL, 3, KOFF(ki_estcpu), UINT, "d", {"cpu", "CPU", NULL, 0, kvar, KOFF(ki_estcpu), UINT, "d", 0},
0}, {"cputime", "", "time", 0, NULL, 0, CHAR, NULL, 0},
{"cputime", "", "time", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"egid", "", "gid", 0, NULL, 0, CHAR, NULL, 0},
{"egid", "", "gid", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"egroup", "", "group", 0, NULL, 0, CHAR, NULL, 0},
{"egroup", "", "group", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"emul", "EMUL", NULL, LJUST, emulname, 0, CHAR, NULL, 0},
{"emul", "EMUL", NULL, LJUST, emulname, NULL, EMULLEN, 0, CHAR, {"etime", "ELAPSED", NULL, USER, elapsed, 0, CHAR, NULL, 0},
NULL, 0}, {"etimes", "ELAPSED", NULL, USER, elapseds, 0, CHAR, NULL, 0},
{"etime", "ELAPSED", NULL, USER, elapsed, NULL, 12, 0, CHAR, NULL, 0}, {"euid", "", "uid", 0, NULL, 0, CHAR, NULL, 0},
{"etimes", "ELAPSED", NULL, USER, elapseds, NULL, 12, 0, CHAR, NULL, 0}, {"f", "F", NULL, 0, kvar, KOFF(ki_flag), INT, "x", 0},
{"euid", "", "uid", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"flags", "", "f", 0, NULL, 0, CHAR, NULL, 0},
{"f", "F", NULL, 0, kvar, NULL, 8, KOFF(ki_flag), INT, "x", 0}, {"gid", "GID", NULL, 0, kvar, KOFF(ki_groups), UINT, UIDFMT, 0},
{"flags", "", "f", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"group", "GROUP", NULL, LJUST, egroupname, 0, CHAR, NULL, 0},
{"gid", "GID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_groups), {"ignored", "", "sigignore", 0, NULL, 0, CHAR, NULL, 0},
UINT, UIDFMT, 0}, {"inblk", "INBLK", NULL, USER, rvar, ROFF(ru_inblock), LONG, "ld", 0},
{"group", "GROUP", NULL, LJUST, egroupname, s_egroupname, {"inblock", "", "inblk", 0, NULL, 0, CHAR, NULL, 0},
USERLEN, 0, CHAR, NULL, 0}, {"jid", "JID", NULL, 0, kvar, KOFF(ki_jid), INT, "d", 0},
{"ignored", "", "sigignore", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"jobc", "JOBC", NULL, 0, kvar, KOFF(ki_jobc), SHORT, "d", 0},
{"inblk", "INBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_inblock), LONG, {"ktrace", "KTRACE", NULL, 0, kvar, KOFF(ki_traceflag), INT, "x", 0},
"ld", 0}, {"label", "LABEL", NULL, LJUST, label, 0, CHAR, NULL, 0},
{"inblock", "", "inblk", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"lim", "LIM", NULL, 0, maxrss, 0, CHAR, NULL, 0},
{"jid", "JID", NULL, 0, kvar, NULL, 6, KOFF(ki_jid), INT, "d", 0}, {"lockname", "LOCK", NULL, LJUST, lockname, 0, CHAR, NULL, 0},
{"jobc", "JOBC", NULL, 0, kvar, NULL, 4, KOFF(ki_jobc), SHORT, "d", {"login", "LOGIN", NULL, LJUST, logname, 0, CHAR, NULL, 0},
0}, {"logname", "", "login", 0, NULL, 0, CHAR, NULL, 0},
{"ktrace", "KTRACE", NULL, 0, kvar, NULL, 8, KOFF(ki_traceflag), INT, {"lstart", "STARTED", NULL, LJUST|USER, lstarted, 0, CHAR, NULL, 0},
"x", 0}, {"lwp", "LWP", NULL, 0, kvar, KOFF(ki_tid), UINT, LWPFMT, 0},
{"label", "LABEL", NULL, LJUST, label, s_label, SHRT_MAX, 0, CHAR, {"majflt", "MAJFLT", NULL, USER, rvar, ROFF(ru_majflt), LONG, "ld", 0},
NULL, 0}, {"minflt", "MINFLT", NULL, USER, rvar, ROFF(ru_minflt), LONG, "ld", 0},
{"lim", "LIM", NULL, 0, maxrss, NULL, 5, 0, CHAR, NULL, 0}, {"msgrcv", "MSGRCV", NULL, USER, rvar, ROFF(ru_msgrcv), LONG, "ld", 0},
{"lockname", "LOCK", NULL, LJUST, lockname, NULL, 6, 0, CHAR, NULL, {"msgsnd", "MSGSND", NULL, USER, rvar, ROFF(ru_msgsnd), LONG, "ld", 0},
0}, {"mwchan", "MWCHAN", NULL, LJUST, mwchan, 0, CHAR, NULL, 0},
{"login", "LOGIN", NULL, LJUST, logname, s_logname, MAXLOGNAME-1, {"ni", "", "nice", 0, NULL, 0, CHAR, NULL, 0},
0, CHAR, NULL, 0}, {"nice", "NI", NULL, 0, kvar, KOFF(ki_nice), CHAR, "d", 0},
{"logname", "", "login", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"nivcsw", "NIVCSW", NULL, USER, rvar, ROFF(ru_nivcsw), LONG, "ld", 0},
{"lstart", "STARTED", NULL, LJUST|USER, lstarted, NULL, 28, 0, CHAR, {"nlwp", "NLWP", NULL, 0, kvar, KOFF(ki_numthreads), UINT, NLWPFMT, 0},
NULL, 0}, {"nsignals", "", "nsigs", 0, NULL, 0, CHAR, NULL, 0},
{"lwp", "LWP", NULL, 0, kvar, NULL, LWPLEN, KOFF(ki_tid), UINT, {"nsigs", "NSIGS", NULL, USER, rvar, ROFF(ru_nsignals), LONG, "ld", 0},
LWPFMT, 0}, {"nswap", "NSWAP", NULL, USER, rvar, ROFF(ru_nswap), LONG, "ld", 0},
{"majflt", "MAJFLT", NULL, USER, rvar, NULL, 4, ROFF(ru_majflt), {"nvcsw", "NVCSW", NULL, USER, rvar, ROFF(ru_nvcsw), LONG, "ld", 0},
LONG, "ld", 0}, {"nwchan", "NWCHAN", NULL, LJUST, nwchan, 0, CHAR, NULL, 0},
{"minflt", "MINFLT", NULL, USER, rvar, NULL, 4, ROFF(ru_minflt), {"oublk", "OUBLK", NULL, USER, rvar, ROFF(ru_oublock), LONG, "ld", 0},
LONG, "ld", 0}, {"oublock", "", "oublk", 0, NULL, 0, CHAR, NULL, 0},
{"msgrcv", "MSGRCV", NULL, USER, rvar, NULL, 4, ROFF(ru_msgrcv), {"paddr", "PADDR", NULL, 0, kvar, KOFF(ki_paddr), KPTR, "lx", 0},
LONG, "ld", 0}, {"pagein", "PAGEIN", NULL, USER, pagein, 0, CHAR, NULL, 0},
{"msgsnd", "MSGSND", NULL, USER, rvar, NULL, 4, ROFF(ru_msgsnd), {"pcpu", "", "%cpu", 0, NULL, 0, CHAR, NULL, 0},
LONG, "ld", 0}, {"pending", "", "sig", 0, NULL, 0, CHAR, NULL, 0},
{"mwchan", "MWCHAN", NULL, LJUST, mwchan, NULL, 6, 0, CHAR, NULL, 0}, {"pgid", "PGID", NULL, 0, kvar, KOFF(ki_pgid), UINT, PIDFMT, 0},
{"ni", "", "nice", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"pid", "PID", NULL, 0, kvar, KOFF(ki_pid), UINT, PIDFMT, 0},
{"nice", "NI", NULL, 0, kvar, NULL, 2, KOFF(ki_nice), CHAR, "d", {"pmem", "", "%mem", 0, NULL, 0, CHAR, NULL, 0},
0}, {"ppid", "PPID", NULL, 0, kvar, KOFF(ki_ppid), UINT, PIDFMT, 0},
{"nivcsw", "NIVCSW", NULL, USER, rvar, NULL, 5, ROFF(ru_nivcsw), {"pri", "PRI", NULL, 0, pri, 0, CHAR, NULL, 0},
LONG, "ld", 0}, {"re", "RE", NULL, INF127, kvar, KOFF(ki_swtime), UINT, "d", 0},
{"nlwp", "NLWP", NULL, 0, kvar, NULL, NLWPLEN, KOFF(ki_numthreads), {"rgid", "RGID", NULL, 0, kvar, KOFF(ki_rgid), UINT, UIDFMT, 0},
UINT, NLWPFMT, 0}, {"rgroup", "RGROUP", NULL, LJUST, rgroupname, 0, CHAR, NULL, 0},
{"nsignals", "", "nsigs", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"rss", "RSS", NULL, 0, kvar, KOFF(ki_rssize), PGTOK, "ld", 0},
{"nsigs", "NSIGS", NULL, USER, rvar, NULL, 4, ROFF(ru_nsignals), {"rtprio", "RTPRIO", NULL, 0, priorityr, KOFF(ki_pri), CHAR, NULL, 0},
LONG, "ld", 0}, {"ruid", "RUID", NULL, 0, kvar, KOFF(ki_ruid), UINT, UIDFMT, 0},
{"nswap", "NSWAP", NULL, USER, rvar, NULL, 4, ROFF(ru_nswap), {"ruser", "RUSER", NULL, LJUST, runame, 0, CHAR, NULL, 0},
LONG, "ld", 0}, {"sid", "SID", NULL, 0, kvar, KOFF(ki_sid), UINT, PIDFMT, 0},
{"nvcsw", "NVCSW", NULL, USER, rvar, NULL, 5, ROFF(ru_nvcsw), {"sig", "PENDING", NULL, 0, kvar, KOFF(ki_siglist), INT, "x", 0},
LONG, "ld", 0}, {"sigcatch", "CAUGHT", NULL, 0, kvar, KOFF(ki_sigcatch), UINT, "x", 0},
{"nwchan", "NWCHAN", NULL, LJUST, nwchan, NULL, sizeof(void *) * 2, 0, {"sigignore", "IGNORED", NULL, 0, kvar, KOFF(ki_sigignore),
CHAR, NULL, 0},
{"oublk", "OUBLK", NULL, USER, rvar, NULL, 4, ROFF(ru_oublock),
LONG, "ld", 0},
{"oublock", "", "oublk", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"paddr", "PADDR", NULL, 0, kvar, NULL, sizeof(void *) * 2,
KOFF(ki_paddr), KPTR, "lx", 0},
{"pagein", "PAGEIN", NULL, USER, pagein, NULL, 6, 0, CHAR, NULL, 0},
{"pcpu", "", "%cpu", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"pending", "", "sig", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"pgid", "PGID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_pgid), UINT,
PIDFMT, 0},
{"pid", "PID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_pid), UINT,
PIDFMT, 0},
{"pmem", "", "%mem", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"ppid", "PPID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_ppid), UINT,
PIDFMT, 0},
{"pri", "PRI", NULL, 0, pri, NULL, 3, 0, CHAR, NULL, 0},
{"re", "RE", NULL, INF127, kvar, NULL, 3, KOFF(ki_swtime), UINT, "d",
0},
{"rgid", "RGID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_rgid),
UINT, UIDFMT, 0},
{"rgroup", "RGROUP", NULL, LJUST, rgroupname, s_rgroupname,
USERLEN, 0, CHAR, NULL, 0},
{"rss", "RSS", NULL, 0, kvar, NULL, 6, KOFF(ki_rssize), PGTOK, "ld", 0},
{"rtprio", "RTPRIO", NULL, 0, priorityr, NULL, 7, KOFF(ki_pri), CHAR,
NULL, 0},
{"ruid", "RUID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_ruid),
UINT, UIDFMT, 0},
{"ruser", "RUSER", NULL, LJUST, runame, s_runame, USERLEN,
0, CHAR, NULL, 0},
{"sid", "SID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_sid), UINT,
PIDFMT, 0},
{"sig", "PENDING", NULL, 0, kvar, NULL, 8, KOFF(ki_siglist), INT,
"x", 0},
{"sigcatch", "CAUGHT", NULL, 0, kvar, NULL, 8, KOFF(ki_sigcatch),
UINT, "x", 0}, UINT, "x", 0},
{"sigignore", "IGNORED", NULL, 0, kvar, NULL, 8, KOFF(ki_sigignore), {"sigmask", "BLOCKED", NULL, 0, kvar, KOFF(ki_sigmask), UINT, "x", 0},
UINT, "x", 0}, {"sl", "SL", NULL, INF127, kvar, KOFF(ki_slptime), UINT, "d", 0},
{"sigmask", "BLOCKED", NULL, 0, kvar, NULL, 8, KOFF(ki_sigmask), {"start", "STARTED", NULL, LJUST|USER, started, 0, CHAR, NULL, 0},
UINT, "x", 0}, {"stat", "", "state", 0, NULL, 0, CHAR, NULL, 0},
{"sl", "SL", NULL, INF127, kvar, NULL, 3, KOFF(ki_slptime), UINT, "d", {"state", "STAT", NULL, LJUST, state, 0, CHAR, NULL, 0},
0}, {"svgid", "SVGID", NULL, 0, kvar, KOFF(ki_svgid), UINT, UIDFMT, 0},
{"start", "STARTED", NULL, LJUST|USER, started, NULL, 7, 0, CHAR, NULL, {"svuid", "SVUID", NULL, 0, kvar, KOFF(ki_svuid), UINT, UIDFMT, 0},
0}, {"systime", "SYSTIME", NULL, USER, systime, 0, CHAR, NULL, 0},
{"stat", "", "state", 0, NULL, NULL, 0, 0, CHAR, NULL, 0}, {"tdaddr", "TDADDR", NULL, 0, kvar, KOFF(ki_tdaddr), KPTR, "lx", 0},
{"state", "STAT", NULL, 0, state, NULL, 4, 0, CHAR, NULL, 0}, {"tdev", "TDEV", NULL, 0, tdev, 0, CHAR, NULL, 0},
{"svgid", "SVGID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_svgid), {"tdnam", "TDNAM", NULL, LJUST, tdnam, 0, CHAR, NULL, 0},
UINT, UIDFMT, 0}, {"time", "TIME", NULL, USER, cputime, 0, CHAR, NULL, 0},
{"svuid", "SVUID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_svuid), {"tpgid", "TPGID", NULL, 0, kvar, KOFF(ki_tpgid), UINT, PIDFMT, 0},
UINT, UIDFMT, 0}, {"tsid", "TSID", NULL, 0, kvar, KOFF(ki_tsid), UINT, PIDFMT, 0},
{"systime", "SYSTIME", NULL, USER, systime, s_systime, 15, 0, CHAR, {"tsiz", "TSIZ", NULL, 0, kvar, KOFF(ki_tsize), PGTOK, "ld", 0},
NULL, 0}, {"tt", "TT ", NULL, 0, tname, 0, CHAR, NULL, 0},
{"tdaddr", "TDADDR", NULL, 0, kvar, NULL, sizeof(void *) * 2, {"tty", "TTY", NULL, LJUST, longtname, 0, CHAR, NULL, 0},
KOFF(ki_tdaddr), KPTR, "lx", 0}, {"ucomm", "UCOMM", NULL, LJUST, ucomm, 0, CHAR, NULL, 0},
{"tdev", "TDEV", NULL, 0, tdev, NULL, 5, 0, CHAR, NULL, 0}, {"uid", "UID", NULL, 0, kvar, KOFF(ki_uid), UINT, UIDFMT, 0},
{"tdnam", "TDNAM", NULL, LJUST, tdnam, NULL, COMMLEN, 0, CHAR, NULL, 0}, {"upr", "UPR", NULL, 0, upr, 0, CHAR, NULL, 0},
{"time", "TIME", NULL, USER, cputime, s_cputime, 15, 0, CHAR, {"uprocp", "UPROCP", NULL, 0, kvar, KOFF(ki_paddr), KPTR, "lx", 0},
NULL, 0}, {"user", "USER", NULL, LJUST, uname, 0, CHAR, NULL, 0},
{"tpgid", "TPGID", NULL, 0, kvar, NULL, 4, KOFF(ki_tpgid), UINT, {"usertime", "USERTIME", NULL, USER, usertime, 0, CHAR, NULL, 0},
PIDFMT, 0}, {"usrpri", "", "upr", 0, NULL, 0, CHAR, NULL, 0},
{"tsid", "TSID", NULL, 0, kvar, NULL, PIDLEN, KOFF(ki_tsid), UINT, {"vsize", "", "vsz", 0, NULL, 0, CHAR, NULL, 0},
PIDFMT, 0}, {"vsz", "VSZ", NULL, 0, vsize, 0, CHAR, NULL, 0},
{"tsiz", "TSIZ", NULL, 0, kvar, NULL, 4, KOFF(ki_tsize), PGTOK, "ld", 0}, {"wchan", "WCHAN", NULL, LJUST, wchan, 0, CHAR, NULL, 0},
{"tt", "TT ", NULL, 0, tname, NULL, 4, 0, CHAR, NULL, 0}, {"xstat", "XSTAT", NULL, 0, kvar, KOFF(ki_xstat), USHORT, "x", 0},
{"tty", "TTY", NULL, LJUST, longtname, NULL, 8, 0, CHAR, NULL, 0}, {"", NULL, NULL, 0, NULL, 0, CHAR, NULL, 0},
{"ucomm", "UCOMM", NULL, LJUST, ucomm, s_comm,
COMMLEN + TDNAMLEN + 1, 0, CHAR, NULL, 0},
{"uid", "UID", NULL, 0, kvar, NULL, UIDLEN, KOFF(ki_uid), UINT,
UIDFMT, 0},
{"upr", "UPR", NULL, 0, upr, NULL, 3, 0, CHAR, NULL, 0},
{"uprocp", "UPROCP", NULL, 0, kvar, NULL, sizeof(void *) * 2,
KOFF(ki_paddr), KPTR, "lx", 0},
{"user", "USER", NULL, LJUST, uname, s_uname, USERLEN, 0, CHAR,
NULL, 0},
{"usertime", "USERTIME", NULL, USER, usertime, s_usertime, 15, 0,
CHAR, NULL, 0},
{"usrpri", "", "upr", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"vsize", "", "vsz", 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
{"vsz", "VSZ", NULL, 0, vsize, NULL, 6, 0, CHAR, NULL, 0},
{"wchan", "WCHAN", NULL, LJUST, wchan, NULL, 6, 0, CHAR, NULL, 0},
{"xstat", "XSTAT", NULL, 0, kvar, NULL, 4, KOFF(ki_xstat), USHORT,
"x", 0},
{"", NULL, NULL, 0, NULL, NULL, 0, 0, CHAR, NULL, 0},
}; };
void void

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@
.\" @(#)ps.1 8.3 (Berkeley) 4/18/94 .\" @(#)ps.1 8.3 (Berkeley) 4/18/94
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd July 1, 2011 .Dd October 1, 2011
.Dt PS 1 .Dt PS 1
.Os .Os
.Sh NAME .Sh NAME
@ -54,6 +54,11 @@ utility
displays a header line, followed by lines containing information about displays a header line, followed by lines containing information about
all of your all of your
processes that have controlling terminals. processes that have controlling terminals.
If the
.Fl x
options is specified,
.Nm
will also display processes that do not have controlling terminals.
.Pp .Pp
A different set of processes can be selected for display by using any A different set of processes can be selected for display by using any
combination of the combination of the
@ -90,8 +95,8 @@ and
.Fl o .Fl o
options). options).
The default output format includes, for each process, the process' ID, The default output format includes, for each process, the process' ID,
controlling terminal, CPU time (including both user and system time), controlling terminal, state, CPU time (including both user and system time)
state, and associated command. and associated command.
.Pp .Pp
The process file system (see The process file system (see
.Xr procfs 5 ) .Xr procfs 5 )
@ -103,13 +108,9 @@ The options are as follows:
.Bl -tag -width indent .Bl -tag -width indent
.It Fl a .It Fl a
Display information about other users' processes as well as your own. Display information about other users' processes as well as your own.
This will skip any processes which do not have a controlling terminal, If the
unless the
.Fl x
option is also specified.
This can be disabled by setting the
.Va security.bsd.see_other_uids .Va security.bsd.see_other_uids
sysctl to zero. sysctl is set to zero, this option is honored only if the UID of the user is 0.
.It Fl c .It Fl c
Change the Change the
.Dq command .Dq command
@ -216,6 +217,9 @@ with the standard input.
.It Fl t .It Fl t
Display information about processes attached to the specified terminal Display information about processes attached to the specified terminal
devices. devices.
Full pathnames, as well as abbreviations (see explanation of the
.Cm tt
keyword) can be specified.
.It Fl U .It Fl U
Display the processes belonging to the specified usernames. Display the processes belonging to the specified usernames.
.It Fl u .It Fl u
@ -427,12 +431,15 @@ The process is being traced or debugged.
An abbreviation for the pathname of the controlling terminal, if any. An abbreviation for the pathname of the controlling terminal, if any.
The abbreviation consists of the three letters following The abbreviation consists of the three letters following
.Pa /dev/tty , .Pa /dev/tty ,
or, for the console, or, for pseudo-terminals, the corresponding entry in
.Dq Li con . .Pa /dev/pts .
This is followed by a This is followed by a
.Ql - .Ql -
if the process can no longer reach that if the process can no longer reach that
controlling terminal (i.e., it has been revoked). controlling terminal (i.e., it has been revoked).
The full pathname of the controlling terminal is available via the
.Cm tty
keyword.
.It Cm wchan .It Cm wchan
The event (an address in the system) on which a process waits. The event (an address in the system) on which a process waits.
When printed numerically, the initial part of the address is When printed numerically, the initial part of the address is

View File

@ -99,14 +99,12 @@ time_t now; /* Current time(3) value */
int rawcpu; /* -C */ int rawcpu; /* -C */
int sumrusage; /* -S */ int sumrusage; /* -S */
int termwidth; /* Width of the screen (0 == infinity). */ int termwidth; /* Width of the screen (0 == infinity). */
int totwidth; /* Calculated-width of requested variables. */
int showthreads; /* will threads be shown? */ int showthreads; /* will threads be shown? */
struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist); struct velisthead varlist = STAILQ_HEAD_INITIALIZER(varlist);
static int forceuread = DEF_UREAD; /* Do extra work to get u-area. */ static int forceuread = DEF_UREAD; /* Do extra work to get u-area. */
static kvm_t *kd; static kvm_t *kd;
static KINFO *kinfo;
static int needcomm; /* -o "command" */ static int needcomm; /* -o "command" */
static int needenv; /* -e */ static int needenv; /* -e */
static int needuser; /* -o "user" */ static int needuser; /* -o "user" */
@ -139,7 +137,7 @@ static int addelem_tty(struct listinfo *, const char *);
static int addelem_uid(struct listinfo *, const char *); static int addelem_uid(struct listinfo *, const char *);
static void add_list(struct listinfo *, const char *); static void add_list(struct listinfo *, const char *);
static void descendant_sort(KINFO *, int); static void descendant_sort(KINFO *, int);
static void dynsizevars(KINFO *); static void format_output(KINFO *);
static void *expand_list(struct listinfo *); static void *expand_list(struct listinfo *);
static const char * static const char *
fmt(char **(*)(kvm_t *, const struct kinfo_proc *, int), fmt(char **(*)(kvm_t *, const struct kinfo_proc *, int),
@ -172,12 +170,13 @@ main(int argc, char *argv[])
struct listinfo gidlist, pgrplist, pidlist; struct listinfo gidlist, pgrplist, pidlist;
struct listinfo ruidlist, sesslist, ttylist, uidlist; struct listinfo ruidlist, sesslist, ttylist, uidlist;
struct kinfo_proc *kp; struct kinfo_proc *kp;
KINFO *next_KINFO; KINFO *kinfo = NULL, *next_KINFO;
KINFO_STR *ks;
struct varent *vent; struct varent *vent;
struct winsize ws; struct winsize ws;
const char *nlistf, *memf; const char *nlistf, *memf, *fmtstr, *str;
char *cols; char *cols;
int all, ch, elem, flag, _fmt, i, lineno; int all, ch, elem, flag, _fmt, i, lineno, linelen, left;
int descendancy, nentries, nkept, nselectors; int descendancy, nentries, nkept, nselectors;
int prtheader, wflag, what, xkeep, xkeep_implied; int prtheader, wflag, what, xkeep, xkeep_implied;
char errbuf[_POSIX2_LINE_MAX]; char errbuf[_POSIX2_LINE_MAX];
@ -588,19 +587,16 @@ main(int argc, char *argv[])
kp->ki_dsize + kp->ki_ssize; kp->ki_dsize + kp->ki_ssize;
if (needuser) if (needuser)
saveuser(next_KINFO); saveuser(next_KINFO);
dynsizevars(next_KINFO);
nkept++; nkept++;
} }
} }
sizevars(); sizevars();
/* if (nkept == 0) {
* print header printheader();
*/
printheader();
if (nkept == 0)
exit(1); exit(1);
}
/* /*
* sort proc list * sort proc list
@ -613,14 +609,59 @@ main(int argc, char *argv[])
if (descendancy) if (descendancy)
descendant_sort(kinfo, nkept); descendant_sort(kinfo, nkept);
/* /*
* For each process, call each variable output function. * Prepare formatted output.
*/
for (i = 0; i < nkept; i++)
format_output(&kinfo[i]);
/*
* Print header.
*/
printheader();
/*
* Output formatted lines.
*/ */
for (i = lineno = 0; i < nkept; i++) { for (i = lineno = 0; i < nkept; i++) {
linelen = 0;
STAILQ_FOREACH(vent, &varlist, next_ve) { STAILQ_FOREACH(vent, &varlist, next_ve) {
(vent->var->oproc)(&kinfo[i], vent); if (vent->var->flag & LJUST)
if (STAILQ_NEXT(vent, next_ve) != NULL) fmtstr = "%-*s";
else
fmtstr = "%*s";
ks = STAILQ_FIRST(&kinfo[i].ki_ks);
STAILQ_REMOVE_HEAD(&kinfo[i].ki_ks, ks_next);
/* Truncate rightmost column if neccessary. */
if (STAILQ_NEXT(vent, next_ve) == NULL &&
termwidth != UNLIMITED && ks->ks_str != NULL) {
left = termwidth - linelen;
if (left > 0 && left < (int)strlen(ks->ks_str))
ks->ks_str[left] = '\0';
}
str = ks->ks_str;
if (str == NULL)
str = "-";
/* No padding for the last column, if it's LJUST. */
if (STAILQ_NEXT(vent, next_ve) == NULL &&
vent->var->flag & LJUST)
linelen += printf(fmtstr, 0, str);
else
linelen += printf(fmtstr, vent->var->width, str);
if (ks->ks_str != NULL) {
free(ks->ks_str);
ks->ks_str = NULL;
}
free(ks);
ks = NULL;
if (STAILQ_NEXT(vent, next_ve) != NULL) {
(void)putchar(' '); (void)putchar(' ');
linelen++;
}
} }
(void)putchar('\n'); (void)putchar('\n');
if (prtheader && lineno++ == prtheader - 4) { if (prtheader && lineno++ == prtheader - 4) {
@ -1078,10 +1119,6 @@ scanvars(void)
STAILQ_FOREACH(vent, &varlist, next_ve) { STAILQ_FOREACH(vent, &varlist, next_ve) {
v = vent->var; v = vent->var;
if (v->sproc != NULL) {
v->dwidth = v->width;
v->width = 0;
}
if (v->flag & USER) if (v->flag & USER)
needuser = 1; needuser = 1;
if (v->flag & COMM) if (v->flag & COMM)
@ -1090,21 +1127,29 @@ scanvars(void)
} }
static void static void
dynsizevars(KINFO *ki) format_output(KINFO *ki)
{ {
struct varent *vent; struct varent *vent;
VAR *v; VAR *v;
int i; KINFO_STR *ks;
char *str;
int len;
STAILQ_INIT(&ki->ki_ks);
STAILQ_FOREACH(vent, &varlist, next_ve) { STAILQ_FOREACH(vent, &varlist, next_ve) {
v = vent->var; v = vent->var;
if (v->sproc == NULL) str = (v->oproc)(ki, vent);
continue; ks = malloc(sizeof(*ks));
i = (v->sproc)(ki); if (ks == NULL)
if (v->width < i) errx(1, "malloc failed");
v->width = i; ks->ks_str = str;
if (v->width > v->dwidth) STAILQ_INSERT_TAIL(&ki->ki_ks, ks, ks_next);
v->width = v->dwidth; if (str != NULL) {
len = strlen(str);
} else
len = 1; /* "-" */
if (v->width < len)
v->width = len;
} }
} }
@ -1120,9 +1165,7 @@ sizevars(void)
i = strlen(vent->header); i = strlen(vent->header);
if (v->width < i) if (v->width < i)
v->width = i; v->width = i;
totwidth += v->width + 1; /* +1 for space */
} }
totwidth--;
} }
static const char * static const char *

View File

@ -35,6 +35,11 @@
#define UNLIMITED 0 /* unlimited terminal width */ #define UNLIMITED 0 /* unlimited terminal width */
enum type { CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG, KPTR, PGTOK }; enum type { CHAR, UCHAR, SHORT, USHORT, INT, UINT, LONG, ULONG, KPTR, PGTOK };
typedef struct kinfo_str {
STAILQ_ENTRY(kinfo_str) ks_next;
char *ks_str; /* formatted string */
} KINFO_STR;
typedef struct kinfo { typedef struct kinfo {
struct kinfo_proc *ki_p; /* kinfo_proc structure */ struct kinfo_proc *ki_p; /* kinfo_proc structure */
char *ki_args; /* exec args */ char *ki_args; /* exec args */
@ -46,6 +51,7 @@ typedef struct kinfo {
int level; /* used in decendant_sort() */ int level; /* used in decendant_sort() */
char *prefix; /* calculated in decendant_sort() */ char *prefix; /* calculated in decendant_sort() */
} ki_d; } ki_d;
STAILQ_HEAD(, kinfo_str) ki_ks;
} KINFO; } KINFO;
/* Variables. */ /* Variables. */
@ -65,10 +71,7 @@ typedef struct var {
#define INF127 0x10 /* values >127 displayed as 127 */ #define INF127 0x10 /* values >127 displayed as 127 */
u_int flag; u_int flag;
/* output routine */ /* output routine */
void (*oproc)(struct kinfo *, struct varent *); char *(*oproc)(struct kinfo *, struct varent *);
/* sizing routine */
int (*sproc)(struct kinfo *);
short width; /* printing width */
/* /*
* The following (optional) elements are hooks for passing information * The following (optional) elements are hooks for passing information
* to the generic output routine pvar (which prints simple elements * to the generic output routine pvar (which prints simple elements
@ -77,10 +80,8 @@ typedef struct var {
size_t off; /* offset in structure */ size_t off; /* offset in structure */
enum type type; /* type of element */ enum type type; /* type of element */
const char *fmt; /* printf format */ const char *fmt; /* printf format */
short dwidth; /* dynamic printing width */
/* short width; /* calculated width */
* glue to link selected fields together
*/
} VAR; } VAR;
#include "extern.h" #include "extern.h"

View File

@ -2190,8 +2190,10 @@ dump_block_stats(spa_t *spa)
*/ */
(void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj, (void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
count_block_cb, &zcb, NULL); count_block_cb, &zcb, NULL);
(void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj, if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
count_block_cb, &zcb, NULL); (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
count_block_cb, &zcb, NULL);
}
if (dump_opt['c'] > 1) if (dump_opt['c'] > 1)
flags |= TRAVERSE_PREFETCH_DATA; flags |= TRAVERSE_PREFETCH_DATA;

View File

@ -74,6 +74,11 @@ zfs \- configures ZFS file systems
\fBzfs\fR \fBrename\fR \fB-r\fR \fIsnapshot\fR \fIsnapshot\fR \fBzfs\fR \fBrename\fR \fB-r\fR \fIsnapshot\fR \fIsnapshot\fR
.fi .fi
.LP
.nf
\fBzfs\fR \fBrename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR
.fi
.LP .LP
.nf .nf
\fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]] \fBzfs\fR \fBlist\fR [\fB-r\fR|\fB-d\fR \fIdepth\fR][\fB-H\fR][\fB-o\fR \fIproperty\fR[,...]] [\fB-t\fR \fItype\fR[,...]]
@ -1479,6 +1484,10 @@ The snapshot that was cloned, and any snapshots previous to this snapshot, are n
.na .na
\fB\fBzfs rename\fR [\fB-p\fR] \fIfilesystem\fR|\fIvolume\fR \fIfilesystem\fR|\fIvolume\fR\fR \fB\fBzfs rename\fR [\fB-p\fR] \fIfilesystem\fR|\fIvolume\fR \fIfilesystem\fR|\fIvolume\fR\fR
.ad .ad
.br
.na
\fB\fBzfs rename\fR \fB-u\fR [\fB-p\fR] \fIfilesystem\fR \fIfilesystem\fR\fR
.ad
.sp .6 .sp .6
.RS 4n .RS 4n
Renames the given dataset. The new target can be located anywhere in the \fBZFS\fR hierarchy, with the exception of snapshots. Snapshots can only be renamed within the parent file system or volume. When renaming a snapshot, the parent file system of the snapshot does not need to be specified as part of the second argument. Renamed file systems can inherit new mount points, in which case they are unmounted and remounted at the new mount point. Renames the given dataset. The new target can be located anywhere in the \fBZFS\fR hierarchy, with the exception of snapshots. Snapshots can only be renamed within the parent file system or volume. When renaming a snapshot, the parent file system of the snapshot does not need to be specified as part of the second argument. Renamed file systems can inherit new mount points, in which case they are unmounted and remounted at the new mount point.
@ -1493,6 +1502,17 @@ Renames the given dataset. The new target can be located anywhere in the \fBZFS\
Creates all the nonexistent parent datasets. Datasets created in this manner are automatically mounted according to the \fBmountpoint\fR property inherited from their parent. Creates all the nonexistent parent datasets. Datasets created in this manner are automatically mounted according to the \fBmountpoint\fR property inherited from their parent.
.RE .RE
.sp
.ne 2
.mk
.na
\fB\fB-u\fR\fR
.ad
.sp .6
.RS 4n
Do not remount file systems during rename. If a file system's \fBmountpoint\fR property is set to \fBlegacy\fR or \fBnone\fR, file system is not unmounted even if this option is not given.
.RE
.RE .RE
.sp .sp

View File

@ -22,6 +22,8 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
*/ */
#include <assert.h> #include <assert.h>
@ -253,7 +255,8 @@ get_usage(zfs_help_t idx)
return (gettext("\trename <filesystem|volume|snapshot> " return (gettext("\trename <filesystem|volume|snapshot> "
"<filesystem|volume|snapshot>\n" "<filesystem|volume|snapshot>\n"
"\trename -p <filesystem|volume> <filesystem|volume>\n" "\trename -p <filesystem|volume> <filesystem|volume>\n"
"\trename -r <snapshot> <snapshot>")); "\trename -r <snapshot> <snapshot>\n"
"\trename -u [-p] <filesystem> <filesystem>"));
case HELP_ROLLBACK: case HELP_ROLLBACK:
return (gettext("\trollback [-rRf] <snapshot>\n")); return (gettext("\trollback [-rRf] <snapshot>\n"));
case HELP_SEND: case HELP_SEND:
@ -2851,6 +2854,7 @@ zfs_do_list(int argc, char **argv)
* zfs rename <fs | snap | vol> <fs | snap | vol> * zfs rename <fs | snap | vol> <fs | snap | vol>
* zfs rename -p <fs | vol> <fs | vol> * zfs rename -p <fs | vol> <fs | vol>
* zfs rename -r <snap> <snap> * zfs rename -r <snap> <snap>
* zfs rename -u [-p] <fs> <fs>
* *
* Renames the given dataset to another of the same type. * Renames the given dataset to another of the same type.
* *
@ -2861,19 +2865,21 @@ static int
zfs_do_rename(int argc, char **argv) zfs_do_rename(int argc, char **argv)
{ {
zfs_handle_t *zhp; zfs_handle_t *zhp;
int c; renameflags_t flags = { 0 };
int ret; int c, ret, types;
boolean_t recurse = B_FALSE;
boolean_t parents = B_FALSE; boolean_t parents = B_FALSE;
/* check options */ /* check options */
while ((c = getopt(argc, argv, "pr")) != -1) { while ((c = getopt(argc, argv, "pru")) != -1) {
switch (c) { switch (c) {
case 'p': case 'p':
parents = B_TRUE; parents = B_TRUE;
break; break;
case 'r': case 'r':
recurse = B_TRUE; flags.recurse = B_TRUE;
break;
case 'u':
flags.nounmount = B_TRUE;
break; break;
case '?': case '?':
default: default:
@ -2902,20 +2908,32 @@ zfs_do_rename(int argc, char **argv)
usage(B_FALSE); usage(B_FALSE);
} }
if (recurse && parents) { if (flags.recurse && parents) {
(void) fprintf(stderr, gettext("-p and -r options are mutually " (void) fprintf(stderr, gettext("-p and -r options are mutually "
"exclusive\n")); "exclusive\n"));
usage(B_FALSE); usage(B_FALSE);
} }
if (recurse && strchr(argv[0], '@') == 0) { if (flags.recurse && strchr(argv[0], '@') == 0) {
(void) fprintf(stderr, gettext("source dataset for recursive " (void) fprintf(stderr, gettext("source dataset for recursive "
"rename must be a snapshot\n")); "rename must be a snapshot\n"));
usage(B_FALSE); usage(B_FALSE);
} }
if ((zhp = zfs_open(g_zfs, argv[0], parents ? ZFS_TYPE_FILESYSTEM | if (flags.nounmount && parents) {
ZFS_TYPE_VOLUME : ZFS_TYPE_DATASET)) == NULL) (void) fprintf(stderr, gettext("-u and -r options are mutually "
"exclusive\n"));
usage(B_FALSE);
}
if (flags.nounmount)
types = ZFS_TYPE_FILESYSTEM;
else if (parents)
types = ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME;
else
types = ZFS_TYPE_DATASET;
if ((zhp = zfs_open(g_zfs, argv[0], types)) == NULL)
return (1); return (1);
/* If we were asked and the name looks good, try to create ancestors. */ /* If we were asked and the name looks good, try to create ancestors. */
@ -2925,7 +2943,7 @@ zfs_do_rename(int argc, char **argv)
return (1); return (1);
} }
ret = (zfs_rename(zhp, argv[1], recurse) != 0); ret = (zfs_rename(zhp, argv[1], flags) != 0);
zfs_close(zhp); zfs_close(zhp);
return (ret); return (ret);

View File

@ -3377,7 +3377,7 @@ print_scan_status(pool_scan_stat_t *ps)
double fraction_done; double fraction_done;
char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7]; char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
(void) printf(gettext(" scan: ")); (void) printf(gettext(" scan: "));
/* If there's never been a scan, there's not much to say. */ /* If there's never been a scan, there's not much to say. */
if (ps == NULL || ps->pss_func == POOL_SCAN_NONE || if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
@ -3457,7 +3457,7 @@ print_scan_status(pool_scan_stat_t *ps)
/* /*
* do not print estimated time if hours_left is more than 30 days * do not print estimated time if hours_left is more than 30 days
*/ */
(void) printf(gettext(" %s scanned out of %s at %s/s"), (void) printf(gettext(" %s scanned out of %s at %s/s"),
examined_buf, total_buf, rate_buf); examined_buf, total_buf, rate_buf);
if (hours_left < (30 * 24)) { if (hours_left < (30 * 24)) {
(void) printf(gettext(", %lluh%um to go\n"), (void) printf(gettext(", %lluh%um to go\n"),
@ -3468,10 +3468,10 @@ print_scan_status(pool_scan_stat_t *ps)
} }
if (ps->pss_func == POOL_SCAN_RESILVER) { if (ps->pss_func == POOL_SCAN_RESILVER) {
(void) printf(gettext(" %s resilvered, %.2f%% done\n"), (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
processed_buf, 100 * fraction_done); processed_buf, 100 * fraction_done);
} else if (ps->pss_func == POOL_SCAN_SCRUB) { } else if (ps->pss_func == POOL_SCAN_SCRUB) {
(void) printf(gettext(" %s repaired, %.2f%% done\n"), (void) printf(gettext(" %s repaired, %.2f%% done\n"),
processed_buf, 100 * fraction_done); processed_buf, 100 * fraction_done);
} }
} }

View File

@ -76,6 +76,7 @@ static __inline int
thr_create(void *stack_base, size_t stack_size, void *(*start_func) (void*), thr_create(void *stack_base, size_t stack_size, void *(*start_func) (void*),
void *arg, long flags, thread_t *new_thread_ID) void *arg, long flags, thread_t *new_thread_ID)
{ {
pthread_t dummy;
int ret; int ret;
assert(stack_base == NULL); assert(stack_base == NULL);
@ -85,9 +86,12 @@ thr_create(void *stack_base, size_t stack_size, void *(*start_func) (void*),
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
if(flags & THR_DETACHED) if (flags & THR_DETACHED)
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (new_thread_ID == NULL)
new_thread_ID = &dummy;
/* This function ignores the THR_BOUND flag, since NPTL doesn't seem to support PTHREAD_SCOPE_PROCESS */ /* This function ignores the THR_BOUND flag, since NPTL doesn't seem to support PTHREAD_SCOPE_PROCESS */
ret = pthread_create(new_thread_ID, &attr, start_func, arg); ret = pthread_create(new_thread_ID, &attr, start_func, arg);

View File

@ -22,6 +22,8 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
*/ */
#ifndef _LIBZFS_H #ifndef _LIBZFS_H
@ -518,7 +520,16 @@ extern int zfs_destroy_snaps(zfs_handle_t *, char *, boolean_t);
extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *); extern int zfs_clone(zfs_handle_t *, const char *, nvlist_t *);
extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *); extern int zfs_snapshot(libzfs_handle_t *, const char *, boolean_t, nvlist_t *);
extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t); extern int zfs_rollback(zfs_handle_t *, zfs_handle_t *, boolean_t);
extern int zfs_rename(zfs_handle_t *, const char *, boolean_t);
typedef struct renameflags {
/* recursive rename */
int recurse : 1;
/* don't unmount file systems */
int nounmount : 1;
} renameflags_t;
extern int zfs_rename(zfs_handle_t *, const char *, renameflags_t flags);
typedef struct sendflags { typedef struct sendflags {
/* print informational messages (ie, -v was specified) */ /* print informational messages (ie, -v was specified) */

View File

@ -24,6 +24,9 @@
* Use is subject to license terms. * Use is subject to license terms.
* *
* Portions Copyright 2007 Ramprakash Jelari * Portions Copyright 2007 Ramprakash Jelari
*
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
*/ */
#include <libintl.h> #include <libintl.h>
@ -122,6 +125,8 @@ changelist_prefix(prop_changelist_t *clp)
*/ */
switch (clp->cl_prop) { switch (clp->cl_prop) {
case ZFS_PROP_MOUNTPOINT: case ZFS_PROP_MOUNTPOINT:
if (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)
break;
if (zfs_unmount(cn->cn_handle, NULL, if (zfs_unmount(cn->cn_handle, NULL,
clp->cl_mflags) != 0) { clp->cl_mflags) != 0) {
ret = -1; ret = -1;
@ -168,8 +173,10 @@ changelist_postfix(prop_changelist_t *clp)
if ((cn = uu_list_last(clp->cl_list)) == NULL) if ((cn = uu_list_last(clp->cl_list)) == NULL)
return (0); return (0);
if (clp->cl_prop == ZFS_PROP_MOUNTPOINT) if (clp->cl_prop == ZFS_PROP_MOUNTPOINT &&
!(clp->cl_gflags & CL_GATHER_DONT_UNMOUNT)) {
remove_mountpoint(cn->cn_handle); remove_mountpoint(cn->cn_handle);
}
/* /*
* It is possible that the changelist_prefix() used libshare * It is possible that the changelist_prefix() used libshare
@ -224,7 +231,8 @@ changelist_postfix(prop_changelist_t *clp)
shareopts, sizeof (shareopts), NULL, NULL, 0, shareopts, sizeof (shareopts), NULL, NULL, 0,
B_FALSE) == 0) && (strcmp(shareopts, "off") != 0)); B_FALSE) == 0) && (strcmp(shareopts, "off") != 0));
mounted = zfs_is_mounted(cn->cn_handle, NULL); mounted = (clp->cl_gflags & CL_GATHER_DONT_UNMOUNT) ||
zfs_is_mounted(cn->cn_handle, NULL);
if (!mounted && (cn->cn_mounted || if (!mounted && (cn->cn_mounted ||
((sharenfs || sharesmb || clp->cl_waslegacy) && ((sharenfs || sharesmb || clp->cl_waslegacy) &&
@ -467,7 +475,6 @@ change_one(zfs_handle_t *zhp, void *data)
* This is necessary when the original mountpoint * This is necessary when the original mountpoint
* is legacy or none. * is legacy or none.
*/ */
ASSERT(!clp->cl_alldependents);
verify(uu_list_insert_before(clp->cl_list, verify(uu_list_insert_before(clp->cl_list,
uu_list_first(clp->cl_list), cn) == 0); uu_list_first(clp->cl_list), cn) == 0);
} }

View File

@ -23,6 +23,8 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2010 Nexenta Systems, Inc. All rights reserved. * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2011 by Delphix. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
*/ */
#include <ctype.h> #include <ctype.h>
@ -3480,7 +3482,7 @@ zfs_iter_dependents(zfs_handle_t *zhp, boolean_t allowrecursion,
* Renames the given dataset. * Renames the given dataset.
*/ */
int int
zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive) zfs_rename(zfs_handle_t *zhp, const char *target, renameflags_t flags)
{ {
int ret; int ret;
zfs_cmd_t zc = { 0 }; zfs_cmd_t zc = { 0 };
@ -3489,6 +3491,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
zfs_handle_t *zhrp = NULL; zfs_handle_t *zhrp = NULL;
char *parentname = NULL; char *parentname = NULL;
char parent[ZFS_MAXNAMELEN]; char parent[ZFS_MAXNAMELEN];
char property[ZFS_MAXPROPLEN];
libzfs_handle_t *hdl = zhp->zfs_hdl; libzfs_handle_t *hdl = zhp->zfs_hdl;
char errbuf[1024]; char errbuf[1024];
@ -3535,7 +3538,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE)) if (!zfs_validate_name(hdl, target, zhp->zfs_type, B_TRUE))
return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf)); return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
} else { } else {
if (recursive) { if (flags.recurse) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"recursive rename must be a snapshot")); "recursive rename must be a snapshot"));
return (zfs_error(hdl, EZFS_BADTYPE, errbuf)); return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
@ -3576,7 +3579,20 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
return (zfs_error(hdl, EZFS_ZONED, errbuf)); return (zfs_error(hdl, EZFS_ZONED, errbuf));
} }
if (recursive) { /*
* Avoid unmounting file systems with mountpoint property set to
* 'legacy' or 'none' even if -u option is not given.
*/
if (zhp->zfs_type == ZFS_TYPE_FILESYSTEM &&
!flags.recurse && !flags.nounmount &&
zfs_prop_get(zhp, ZFS_PROP_MOUNTPOINT, property,
sizeof (property), NULL, NULL, 0, B_FALSE) == 0 &&
(strcmp(property, "legacy") == 0 ||
strcmp(property, "none") == 0)) {
flags.nounmount = B_TRUE;
}
if (flags.recurse) {
parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name); parentname = zfs_strdup(zhp->zfs_hdl, zhp->zfs_name);
if (parentname == NULL) { if (parentname == NULL) {
@ -3592,8 +3608,10 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
} }
} else { } else {
if ((cl = changelist_gather(zhp, ZFS_PROP_NAME, 0, 0)) == NULL) if ((cl = changelist_gather(zhp, ZFS_PROP_NAME,
flags.nounmount ? CL_GATHER_DONT_UNMOUNT : 0, 0)) == NULL) {
return (-1); return (-1);
}
if (changelist_haszonedchild(cl)) { if (changelist_haszonedchild(cl)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@ -3615,7 +3633,9 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
(void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name)); (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
(void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value)); (void) strlcpy(zc.zc_value, target, sizeof (zc.zc_value));
zc.zc_cookie = recursive; zc.zc_cookie = flags.recurse ? 1 : 0;
if (flags.nounmount)
zc.zc_cookie |= 2;
if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) { if ((ret = zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_RENAME, &zc)) != 0) {
/* /*
@ -3625,7 +3645,7 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot rename '%s'"), zc.zc_name); "cannot rename '%s'"), zc.zc_name);
if (recursive && errno == EEXIST) { if (flags.recurse && errno == EEXIST) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"a child dataset already has a snapshot " "a child dataset already has a snapshot "
"with the new name")); "with the new name"));
@ -3638,10 +3658,10 @@ zfs_rename(zfs_handle_t *zhp, const char *target, boolean_t recursive)
* On failure, we still want to remount any filesystems that * On failure, we still want to remount any filesystems that
* were previously mounted, so we don't alter the system state. * were previously mounted, so we don't alter the system state.
*/ */
if (!recursive) if (!flags.recurse)
(void) changelist_postfix(cl); (void) changelist_postfix(cl);
} else { } else {
if (!recursive) { if (!flags.recurse) {
changelist_rename(cl, zfs_get_name(zhp), target); changelist_rename(cl, zfs_get_name(zhp), target);
ret = changelist_postfix(cl); ret = changelist_postfix(cl);
} }

View File

@ -21,6 +21,8 @@
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net>.
* All rights reserved.
*/ */
#ifndef _LIBFS_IMPL_H #ifndef _LIBFS_IMPL_H
@ -158,7 +160,11 @@ int zprop_expand_list(libzfs_handle_t *hdl, zprop_list_t **plp,
* on each change node regardless of whether or not it is currently * on each change node regardless of whether or not it is currently
* mounted. * mounted.
*/ */
#define CL_GATHER_MOUNT_ALWAYS 1 #define CL_GATHER_MOUNT_ALWAYS 0x01
/*
* Use this changelist_gather() flag to prevent unmounting of file systems.
*/
#define CL_GATHER_DONT_UNMOUNT 0x02
typedef struct prop_changelist prop_changelist_t; typedef struct prop_changelist prop_changelist_t;

View File

@ -87,7 +87,7 @@ again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
} }
mutex_exit(&tq->tq_lock); mutex_exit(&tq->tq_lock);
t = kmem_alloc(sizeof (task_t), tqflags); t = kmem_alloc(sizeof (task_t), tqflags & KM_SLEEP);
mutex_enter(&tq->tq_lock); mutex_enter(&tq->tq_lock);
if (t != NULL) if (t != NULL)

View File

@ -1 +1 @@
4.2.2 4.2.1

View File

@ -1 +1 @@
prerelease patched

View File

@ -34,7 +34,7 @@
#ifndef __cplusplus #ifndef __cplusplus
extern int posix_memalign (void **, size_t, size_t); extern int posix_memalign (void **, size_t, size_t);
#else #else
extern "C" int posix_memalign (void **, size_t, size_t) throw (); extern "C" int posix_memalign (void **, size_t, size_t);
#endif #endif
static __inline void * static __inline void *

69
contrib/llvm/LICENSE.TXT Normal file
View File

@ -0,0 +1,69 @@
==============================================================================
LLVM Release License
==============================================================================
University of Illinois/NCSA
Open Source License
Copyright (c) 2003-2011 University of Illinois at Urbana-Champaign.
All rights reserved.
Developed by:
LLVM Team
University of Illinois at Urbana-Champaign
http://llvm.org
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal with
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimers.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimers in the
documentation and/or other materials provided with the distribution.
* Neither the names of the LLVM Team, University of Illinois at
Urbana-Champaign, nor the names of its contributors may be used to
endorse or promote products derived from this Software without specific
prior written permission.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
SOFTWARE.
==============================================================================
Copyrights and Licenses for Third Party Software Distributed with LLVM:
==============================================================================
The LLVM software contains code written by third parties. Such software will
have its own individual LICENSE.TXT file in the directory in which it appears.
This file will describe the copyrights, license, and restrictions which apply
to that code.
The disclaimer of warranty in the University of Illinois Open Source License
applies to all code in the LLVM Distribution, and nothing in any of the
other licenses gives permission to use the names of the LLVM Team or the
University of Illinois to endorse or promote products derived from this
Software.
The following pieces of software have additional or alternate copyrights,
licenses, and/or restrictions:
Program Directory
------- ---------
Autoconf llvm/autoconf
llvm/projects/ModuleMaker/autoconf
llvm/projects/sample/autoconf
CellSPU backend llvm/lib/Target/CellSPU/README.txt
Google Test llvm/utils/unittest/googletest
OpenBSD regex llvm/lib/Support/{reg*, COPYRIGHT.regex}

View File

@ -115,7 +115,10 @@ typedef enum {
LLVMNoImplicitFloatAttribute = 1<<23, LLVMNoImplicitFloatAttribute = 1<<23,
LLVMNakedAttribute = 1<<24, LLVMNakedAttribute = 1<<24,
LLVMInlineHintAttribute = 1<<25, LLVMInlineHintAttribute = 1<<25,
LLVMStackAlignment = 7<<26 LLVMStackAlignment = 7<<26,
LLVMReturnsTwice = 1 << 29,
LLVMUWTable = 1 << 30,
LLVMNonLazyBind = 1 << 31
} LLVMAttribute; } LLVMAttribute;
typedef enum { typedef enum {
@ -125,7 +128,7 @@ typedef enum {
LLVMSwitch = 3, LLVMSwitch = 3,
LLVMIndirectBr = 4, LLVMIndirectBr = 4,
LLVMInvoke = 5, LLVMInvoke = 5,
LLVMUnwind = 6, /* removed 6 due to API changes */
LLVMUnreachable = 7, LLVMUnreachable = 7,
/* Standard Binary Operators */ /* Standard Binary Operators */
@ -176,14 +179,26 @@ typedef enum {
LLVMPHI = 44, LLVMPHI = 44,
LLVMCall = 45, LLVMCall = 45,
LLVMSelect = 46, LLVMSelect = 46,
/* UserOp1 */ LLVMUserOp1 = 47,
/* UserOp2 */ LLVMUserOp2 = 48,
LLVMVAArg = 49, LLVMVAArg = 49,
LLVMExtractElement = 50, LLVMExtractElement = 50,
LLVMInsertElement = 51, LLVMInsertElement = 51,
LLVMShuffleVector = 52, LLVMShuffleVector = 52,
LLVMExtractValue = 53, LLVMExtractValue = 53,
LLVMInsertValue = 54 LLVMInsertValue = 54,
/* Atomic operators */
LLVMFence = 55,
LLVMAtomicCmpXchg = 56,
LLVMAtomicRMW = 57,
/* Exception Handling Operators */
LLVMResume = 58,
LLVMLandingPad = 59,
LLVMUnwind = 60
} LLVMOpcode; } LLVMOpcode;
typedef enum { typedef enum {
@ -274,6 +289,11 @@ typedef enum {
LLVMRealPredicateTrue /**< Always true (always folded) */ LLVMRealPredicateTrue /**< Always true (always folded) */
} LLVMRealPredicate; } LLVMRealPredicate;
typedef enum {
LLVMLandingPadCatch, /**< A catch clause */
LLVMLandingPadFilter /**< A filter clause */
} LLVMLandingPadClauseTy;
void LLVMInitializeCore(LLVMPassRegistryRef R); void LLVMInitializeCore(LLVMPassRegistryRef R);
@ -340,6 +360,7 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M);
/** See llvm::LLVMTypeKind::getTypeID. */ /** See llvm::LLVMTypeKind::getTypeID. */
LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty); LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty);
LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty);
/** See llvm::LLVMType::getContext. */ /** See llvm::LLVMType::getContext. */
LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty); LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty);
@ -388,6 +409,7 @@ LLVMTypeRef LLVMStructTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes,
LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount, LLVMTypeRef LLVMStructType(LLVMTypeRef *ElementTypes, unsigned ElementCount,
LLVMBool Packed); LLVMBool Packed);
LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name); LLVMTypeRef LLVMStructCreateNamed(LLVMContextRef C, const char *Name);
const char *LLVMGetStructName(LLVMTypeRef Ty);
void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes, void LLVMStructSetBody(LLVMTypeRef StructTy, LLVMTypeRef *ElementTypes,
unsigned ElementCount, LLVMBool Packed); unsigned ElementCount, LLVMBool Packed);
@ -427,8 +449,11 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(Argument) \ macro(Argument) \
macro(BasicBlock) \ macro(BasicBlock) \
macro(InlineAsm) \ macro(InlineAsm) \
macro(MDNode) \
macro(MDString) \
macro(User) \ macro(User) \
macro(Constant) \ macro(Constant) \
macro(BlockAddress) \
macro(ConstantAggregateZero) \ macro(ConstantAggregateZero) \
macro(ConstantArray) \ macro(ConstantArray) \
macro(ConstantExpr) \ macro(ConstantExpr) \
@ -448,29 +473,32 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(IntrinsicInst) \ macro(IntrinsicInst) \
macro(DbgInfoIntrinsic) \ macro(DbgInfoIntrinsic) \
macro(DbgDeclareInst) \ macro(DbgDeclareInst) \
macro(EHExceptionInst) \
macro(EHSelectorInst) \ macro(EHSelectorInst) \
macro(MemIntrinsic) \ macro(MemIntrinsic) \
macro(MemCpyInst) \ macro(MemCpyInst) \
macro(MemMoveInst) \ macro(MemMoveInst) \
macro(MemSetInst) \ macro(MemSetInst) \
macro(CmpInst) \ macro(CmpInst) \
macro(FCmpInst) \ macro(FCmpInst) \
macro(ICmpInst) \ macro(ICmpInst) \
macro(ExtractElementInst) \ macro(ExtractElementInst) \
macro(GetElementPtrInst) \ macro(GetElementPtrInst) \
macro(InsertElementInst) \ macro(InsertElementInst) \
macro(InsertValueInst) \ macro(InsertValueInst) \
macro(LandingPadInst) \
macro(PHINode) \ macro(PHINode) \
macro(SelectInst) \ macro(SelectInst) \
macro(ShuffleVectorInst) \ macro(ShuffleVectorInst) \
macro(StoreInst) \ macro(StoreInst) \
macro(TerminatorInst) \ macro(TerminatorInst) \
macro(BranchInst) \ macro(BranchInst) \
macro(IndirectBrInst) \
macro(InvokeInst) \ macro(InvokeInst) \
macro(ReturnInst) \ macro(ReturnInst) \
macro(SwitchInst) \ macro(SwitchInst) \
macro(UnreachableInst) \ macro(UnreachableInst) \
macro(UnwindInst) \ macro(ResumeInst) \
macro(UnaryInstruction) \ macro(UnaryInstruction) \
macro(AllocaInst) \ macro(AllocaInst) \
macro(CastInst) \ macro(CastInst) \
@ -533,6 +561,11 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen);
LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
unsigned Count); unsigned Count);
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count); LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len);
int LLVMGetMDNodeNumOperands(LLVMValueRef V);
LLVMValueRef *LLVMGetMDNodeOperand(LLVMValueRef V, unsigned i);
unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name);
void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRef *Dest);
/* Operations on scalar constants */ /* Operations on scalar constants */
LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N,
@ -728,6 +761,7 @@ LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB);
LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val); LLVMBool LLVMValueIsBasicBlock(LLVMValueRef Val);
LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val); LLVMBasicBlockRef LLVMValueAsBasicBlock(LLVMValueRef Val);
LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB); LLVMValueRef LLVMGetBasicBlockParent(LLVMBasicBlockRef BB);
LLVMValueRef LLVMGetBasicBlockTerminator(LLVMBasicBlockRef BB);
unsigned LLVMCountBasicBlocks(LLVMValueRef Fn); unsigned LLVMCountBasicBlocks(LLVMValueRef Fn);
void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks); void LLVMGetBasicBlocks(LLVMValueRef Fn, LLVMBasicBlockRef *BasicBlocks);
LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn); LLVMBasicBlockRef LLVMGetFirstBasicBlock(LLVMValueRef Fn);
@ -747,16 +781,21 @@ LLVMBasicBlockRef LLVMAppendBasicBlock(LLVMValueRef Fn, const char *Name);
LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB, LLVMBasicBlockRef LLVMInsertBasicBlock(LLVMBasicBlockRef InsertBeforeBB,
const char *Name); const char *Name);
void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB); void LLVMDeleteBasicBlock(LLVMBasicBlockRef BB);
void LLVMRemoveBasicBlockFromParent(LLVMBasicBlockRef BB);
void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); void LLVMMoveBasicBlockBefore(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos);
void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos); void LLVMMoveBasicBlockAfter(LLVMBasicBlockRef BB, LLVMBasicBlockRef MovePos);
/* Operations on instructions */
LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst);
LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB); LLVMValueRef LLVMGetFirstInstruction(LLVMBasicBlockRef BB);
LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB); LLVMValueRef LLVMGetLastInstruction(LLVMBasicBlockRef BB);
/* Operations on instructions */
LLVMBasicBlockRef LLVMGetInstructionParent(LLVMValueRef Inst);
LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst); LLVMValueRef LLVMGetNextInstruction(LLVMValueRef Inst);
LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst); LLVMValueRef LLVMGetPreviousInstruction(LLVMValueRef Inst);
void LLVMInstructionEraseFromParent(LLVMValueRef Inst);
LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst);
LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst);
/* Operations on call sites */ /* Operations on call sites */
void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC); void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC);
@ -771,6 +810,9 @@ void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index,
LLVMBool LLVMIsTailCall(LLVMValueRef CallInst); LLVMBool LLVMIsTailCall(LLVMValueRef CallInst);
void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall);
/* Operations on switch instructions (only) */
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr);
/* Operations on phi nodes */ /* Operations on phi nodes */
void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues, void LLVMAddIncoming(LLVMValueRef PhiNode, LLVMValueRef *IncomingValues,
LLVMBasicBlockRef *IncomingBlocks, unsigned Count); LLVMBasicBlockRef *IncomingBlocks, unsigned Count);
@ -818,7 +860,10 @@ LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs, LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name); const char *Name);
LLVMValueRef LLVMBuildUnwind(LLVMBuilderRef); LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef PersFn, unsigned NumClauses,
const char *Name);
LLVMValueRef LLVMBuildResume(LLVMBuilderRef B, LLVMValueRef Exn);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef); LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
/* Add a case to the switch instruction */ /* Add a case to the switch instruction */
@ -828,6 +873,12 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal,
/* Add a destination to the indirectbr instruction */ /* Add a destination to the indirectbr instruction */
void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest); void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest);
/* Add a catch or filter clause to the landingpad instruction */
void LLVMAddClause(LLVMValueRef LandingPad, LLVMValueRef ClauseVal);
/* Set the 'cleanup' flag in the landingpad instruction */
void LLVMSetCleanup(LLVMValueRef LandingPad, LLVMBool Val);
/* Arithmetic */ /* Arithmetic */
LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS, LLVMValueRef LLVMBuildAdd(LLVMBuilderRef, LLVMValueRef LHS, LLVMValueRef RHS,
const char *Name); const char *Name);
@ -1136,7 +1187,7 @@ namespace llvm {
return reinterpret_cast<Type**>(Tys); return reinterpret_cast<Type**>(Tys);
} }
inline LLVMTypeRef *wrap(const Type **Tys) { inline LLVMTypeRef *wrap(Type **Tys) {
return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys)); return reinterpret_cast<LLVMTypeRef*>(const_cast<Type**>(Tys));
} }

View File

@ -66,7 +66,7 @@ typedef int (*LLVMOpInfoCallback)(void *DisInfo, uint64_t PC,
*/ */
struct LLVMOpInfoSymbol1 { struct LLVMOpInfoSymbol1 {
uint64_t Present; /* 1 if this symbol is present */ uint64_t Present; /* 1 if this symbol is present */
char *Name; /* symbol name if not NULL */ const char *Name; /* symbol name if not NULL */
uint64_t Value; /* symbol value if name is NULL */ uint64_t Value; /* symbol value if name is NULL */
}; };
@ -93,11 +93,35 @@ struct LLVMOpInfo1 {
* disassembler for things like adding a comment for a PC plus a constant * disassembler for things like adding a comment for a PC plus a constant
* offset load instruction to use a symbol name instead of a load address value. * offset load instruction to use a symbol name instead of a load address value.
* It is passed the block information is saved when the disassembler context is * It is passed the block information is saved when the disassembler context is
* created and a value of a symbol to look up. If no symbol is found NULL is * created and the ReferenceValue to look up as a symbol. If no symbol is found
* returned. * for the ReferenceValue NULL is returned. The ReferenceType of the
* instruction is passed indirectly as is the PC of the instruction in
* ReferencePC. If the output reference can be determined its type is returned
* indirectly in ReferenceType along with ReferenceName if any, or that is set
* to NULL.
*/ */
typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo, typedef const char *(*LLVMSymbolLookupCallback)(void *DisInfo,
uint64_t SymbolValue); uint64_t ReferenceValue,
uint64_t *ReferenceType,
uint64_t ReferencePC,
const char **ReferenceName);
/**
* The reference types on input and output.
*/
/* No input reference type or no output reference type. */
#define LLVMDisassembler_ReferenceType_InOut_None 0
/* The input reference is from a branch instruction. */
#define LLVMDisassembler_ReferenceType_In_Branch 1
/* The input reference is from a PC relative load instruction. */
#define LLVMDisassembler_ReferenceType_In_PCrel_Load 2
/* The output reference is to as symbol stub. */
#define LLVMDisassembler_ReferenceType_Out_SymbolStub 1
/* The output reference is to a symbol address in a literal pool. */
#define LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr 2
/* The output reference is to a cstring address in a literal pool. */
#define LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr 3
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {

View File

@ -59,14 +59,14 @@ namespace llvm {
return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF)); return reinterpret_cast<LLVMObjectFileRef>(const_cast<ObjectFile*>(OF));
} }
inline ObjectFile::section_iterator *unwrap(LLVMSectionIteratorRef SI) { inline section_iterator *unwrap(LLVMSectionIteratorRef SI) {
return reinterpret_cast<ObjectFile::section_iterator*>(SI); return reinterpret_cast<section_iterator*>(SI);
} }
inline LLVMSectionIteratorRef inline LLVMSectionIteratorRef
wrap(const ObjectFile::section_iterator *SI) { wrap(const section_iterator *SI) {
return reinterpret_cast<LLVMSectionIteratorRef> return reinterpret_cast<LLVMSectionIteratorRef>
(const_cast<ObjectFile::section_iterator*>(SI)); (const_cast<section_iterator*>(SI));
} }
} }
} }

View File

@ -29,6 +29,7 @@ extern "C" {
enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian }; enum LLVMByteOrdering { LLVMBigEndian, LLVMLittleEndian };
typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
typedef struct LLVMOpaqueTargetLibraryInfotData *LLVMTargetLibraryInfoRef;
typedef struct LLVMStructLayout *LLVMStructLayoutRef; typedef struct LLVMStructLayout *LLVMStructLayoutRef;
/* Declare all of the target-initialization functions that are available. */ /* Declare all of the target-initialization functions that are available. */
@ -42,7 +43,7 @@ typedef struct LLVMStructLayout *LLVMStructLayoutRef;
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ #undef LLVM_TARGET /* Explicit undef to make SWIG happier */
#define LLVM_TARGET(TargetName) \ #define LLVM_TARGET(TargetName) \
void LLVMInitialize##TargetName##MCAsmInfo(void); void LLVMInitialize##TargetName##TargetMC(void);
#include "llvm/Config/Targets.def" #include "llvm/Config/Targets.def"
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */ #undef LLVM_TARGET /* Explicit undef to make SWIG happier */
@ -72,7 +73,7 @@ static inline LLVMBool LLVMInitializeNativeTarget(void) {
#ifdef LLVM_NATIVE_TARGET #ifdef LLVM_NATIVE_TARGET
LLVM_NATIVE_TARGETINFO(); LLVM_NATIVE_TARGETINFO();
LLVM_NATIVE_TARGET(); LLVM_NATIVE_TARGET();
LLVM_NATIVE_MCASMINFO(); LLVM_NATIVE_TARGETMC();
return 0; return 0;
#else #else
return 1; return 1;
@ -90,6 +91,11 @@ LLVMTargetDataRef LLVMCreateTargetData(const char *StringRep);
See the method llvm::PassManagerBase::add. */ See the method llvm::PassManagerBase::add. */
void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef); void LLVMAddTargetData(LLVMTargetDataRef, LLVMPassManagerRef);
/** Adds target library information to a pass manager. This does not take
ownership of the target library info.
See the method llvm::PassManagerBase::add. */
void LLVMAddTargetLibraryInfo(LLVMTargetLibraryInfoRef, LLVMPassManagerRef);
/** Converts target data to a target layout string. The string must be disposed /** Converts target data to a target layout string. The string must be disposed
with LLVMDisposeMessage. with LLVMDisposeMessage.
See the constructor llvm::TargetData::TargetData. */ See the constructor llvm::TargetData::TargetData. */
@ -157,6 +163,7 @@ void LLVMDisposeTargetData(LLVMTargetDataRef);
namespace llvm { namespace llvm {
class TargetData; class TargetData;
class TargetLibraryInfo;
inline TargetData *unwrap(LLVMTargetDataRef P) { inline TargetData *unwrap(LLVMTargetDataRef P) {
return reinterpret_cast<TargetData*>(P); return reinterpret_cast<TargetData*>(P);
@ -165,6 +172,15 @@ namespace llvm {
inline LLVMTargetDataRef wrap(const TargetData *P) { inline LLVMTargetDataRef wrap(const TargetData *P) {
return reinterpret_cast<LLVMTargetDataRef>(const_cast<TargetData*>(P)); return reinterpret_cast<LLVMTargetDataRef>(const_cast<TargetData*>(P));
} }
inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef P) {
return reinterpret_cast<TargetLibraryInfo*>(P);
}
inline LLVMTargetLibraryInfoRef wrap(const TargetLibraryInfo *P) {
TargetLibraryInfo *X = const_cast<TargetLibraryInfo*>(P);
return reinterpret_cast<LLVMTargetLibraryInfoRef>(X);
}
} }
#endif /* defined(__cplusplus) */ #endif /* defined(__cplusplus) */

View File

@ -36,6 +36,9 @@ void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM);
/** See llvm::createFunctionInliningPass function. */ /** See llvm::createFunctionInliningPass function. */
void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM); void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM);
/** See llvm::createAlwaysInlinerPass function. */
void LLVMAddAlwaysInlinerPass(LLVMPassManagerRef PM);
/** See llvm::createGlobalDCEPass function. */ /** See llvm::createGlobalDCEPass function. */
void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM); void LLVMAddGlobalDCEPass(LLVMPassManagerRef PM);
@ -45,9 +48,6 @@ void LLVMAddGlobalOptimizerPass(LLVMPassManagerRef PM);
/** See llvm::createIPConstantPropagationPass function. */ /** See llvm::createIPConstantPropagationPass function. */
void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM); void LLVMAddIPConstantPropagationPass(LLVMPassManagerRef PM);
/** See llvm::createLowerSetJmpPass function. */
void LLVMAddLowerSetJmpPass(LLVMPassManagerRef PM);
/** See llvm::createPruneEHPass function. */ /** See llvm::createPruneEHPass function. */
void LLVMAddPruneEHPass(LLVMPassManagerRef PM); void LLVMAddPruneEHPass(LLVMPassManagerRef PM);
@ -57,9 +57,6 @@ void LLVMAddIPSCCPPass(LLVMPassManagerRef PM);
/** See llvm::createInternalizePass function. */ /** See llvm::createInternalizePass function. */
void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain); void LLVMAddInternalizePass(LLVMPassManagerRef, unsigned AllButMain);
// FIXME: Remove in LLVM 3.0.
void LLVMAddRaiseAllocationsPass(LLVMPassManagerRef PM);
/** See llvm::createStripDeadPrototypesPass function. */ /** See llvm::createStripDeadPrototypesPass function. */
void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM); void LLVMAddStripDeadPrototypesPass(LLVMPassManagerRef PM);

View File

@ -0,0 +1,90 @@
/*===-- llvm-c/Transform/PassManagerBuilder.h - PMB C Interface ---*- C -*-===*\
|* *|
|* The LLVM Compiler Infrastructure *|
|* *|
|* This file is distributed under the University of Illinois Open Source *|
|* License. See LICENSE.TXT for details. *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to the PassManagerBuilder class. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_PASSMANAGERBUILDER
#define LLVM_C_PASSMANAGERBUILDER
#include "llvm-c/Core.h"
typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef;
#ifdef __cplusplus
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
extern "C" {
#endif
/** See llvm::PassManagerBuilder. */
LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void);
void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB);
/** See llvm::PassManagerBuilder::OptLevel. */
void
LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB,
unsigned OptLevel);
/** See llvm::PassManagerBuilder::SizeLevel. */
void
LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB,
unsigned SizeLevel);
/** See llvm::PassManagerBuilder::DisableUnitAtATime. */
void
LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB,
LLVMBool Value);
/** See llvm::PassManagerBuilder::DisableUnrollLoops. */
void
LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB,
LLVMBool Value);
/** See llvm::PassManagerBuilder::DisableSimplifyLibCalls */
void
LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB,
LLVMBool Value);
/** See llvm::PassManagerBuilder::Inliner. */
void
LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB,
unsigned Threshold);
/** See llvm::PassManagerBuilder::populateFunctionPassManager. */
void
LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB,
LLVMPassManagerRef PM);
/** See llvm::PassManagerBuilder::populateModulePassManager. */
void
LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB,
LLVMPassManagerRef PM);
/** See llvm::PassManagerBuilder::populateLTOPassManager. */
void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB,
LLVMPassManagerRef PM,
bool Internalize,
bool RunInliner);
#ifdef __cplusplus
}
namespace llvm {
inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) {
return reinterpret_cast<PassManagerBuilder*>(P);
}
inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) {
return reinterpret_cast<LLVMPassManagerBuilderRef>(P);
}
}
#endif
#endif

View File

@ -107,6 +107,9 @@ void LLVMAddCorrelatedValuePropagationPass(LLVMPassManagerRef PM);
/** See llvm::createEarlyCSEPass function */ /** See llvm::createEarlyCSEPass function */
void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM);
/** See llvm::createLowerExpectIntrinsicPass function */
void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM);
/** See llvm::createTypeBasedAliasAnalysisPass function */ /** See llvm::createTypeBasedAliasAnalysisPass function */
void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM);

View File

@ -15,6 +15,7 @@
#ifndef LLVM_APINT_H #ifndef LLVM_APINT_H
#define LLVM_APINT_H #define LLVM_APINT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/MathExtras.h" #include "llvm/Support/MathExtras.h"
#include <cassert> #include <cassert>
#include <climits> #include <climits>
@ -160,7 +161,7 @@ class APInt {
/// not assume that the string is well-formed and (2) grows the /// not assume that the string is well-formed and (2) grows the
/// result to hold the input. /// result to hold the input.
/// ///
/// @param radix 2, 8, 10, or 16 /// @param radix 2, 8, 10, 16, or 36
/// @brief Convert a char array into an APInt /// @brief Convert a char array into an APInt
void fromString(unsigned numBits, StringRef str, uint8_t radix); void fromString(unsigned numBits, StringRef str, uint8_t radix);
@ -176,6 +177,9 @@ class APInt {
/// out-of-line slow case for inline constructor /// out-of-line slow case for inline constructor
void initSlowCase(unsigned numBits, uint64_t val, bool isSigned); void initSlowCase(unsigned numBits, uint64_t val, bool isSigned);
/// shared code between two array constructors
void initFromArray(ArrayRef<uint64_t> array);
/// out-of-line slow case for inline copy constructor /// out-of-line slow case for inline copy constructor
void initSlowCase(const APInt& that); void initSlowCase(const APInt& that);
@ -230,19 +234,26 @@ class APInt {
clearUnusedBits(); clearUnusedBits();
} }
/// Note that numWords can be smaller or larger than the corresponding bit /// Note that bigVal.size() can be smaller or larger than the corresponding
/// width but any extraneous bits will be dropped. /// bit width but any extraneous bits will be dropped.
/// @param numBits the bit width of the constructed APInt /// @param numBits the bit width of the constructed APInt
/// @param numWords the number of words in bigVal
/// @param bigVal a sequence of words to form the initial value of the APInt /// @param bigVal a sequence of words to form the initial value of the APInt
/// @brief Construct an APInt of numBits width, initialized as bigVal[]. /// @brief Construct an APInt of numBits width, initialized as bigVal[].
APInt(unsigned numBits, ArrayRef<uint64_t> bigVal);
/// Equivalent to APInt(numBits, ArrayRef<uint64_t>(bigVal, numWords)), but
/// deprecated because this constructor is prone to ambiguity with the
/// APInt(unsigned, uint64_t, bool) constructor.
///
/// If this overload is ever deleted, care should be taken to prevent calls
/// from being incorrectly captured by the APInt(unsigned, uint64_t, bool)
/// constructor.
APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]); APInt(unsigned numBits, unsigned numWords, const uint64_t bigVal[]);
/// This constructor interprets the string \arg str in the given radix. The /// This constructor interprets the string \arg str in the given radix. The
/// interpretation stops when the first character that is not suitable for the /// interpretation stops when the first character that is not suitable for the
/// radix is encountered, or the end of the string. Acceptable radix values /// radix is encountered, or the end of the string. Acceptable radix values
/// are 2, 8, 10 and 16. It is an error for the value implied by the string to /// are 2, 8, 10, 16, and 36. It is an error for the value implied by the
/// require more bits than numBits. /// string to require more bits than numBits.
/// ///
/// @param numBits the bit width of the constructed APInt /// @param numBits the bit width of the constructed APInt
/// @param str the string to be interpreted /// @param str the string to be interpreted
@ -342,7 +353,8 @@ class APInt {
if (isSingleWord()) if (isSingleWord())
return isUIntN(N, VAL); return isUIntN(N, VAL);
return APInt(N, getNumWords(), pVal).zext(getBitWidth()) == (*this); return APInt(N, makeArrayRef(pVal, getNumWords())).zext(getBitWidth())
== (*this);
} }
/// @brief Check if this APInt has an N-bits signed integer value. /// @brief Check if this APInt has an N-bits signed integer value.
@ -1245,13 +1257,13 @@ class APInt {
bool formatAsCLiteral = false) const; bool formatAsCLiteral = false) const;
/// Considers the APInt to be unsigned and converts it into a string in the /// Considers the APInt to be unsigned and converts it into a string in the
/// radix given. The radix can be 2, 8, 10 or 16. /// radix given. The radix can be 2, 8, 10 16, or 36.
void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { void toStringUnsigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
toString(Str, Radix, false, false); toString(Str, Radix, false, false);
} }
/// Considers the APInt to be signed and converts it into a string in the /// Considers the APInt to be signed and converts it into a string in the
/// radix given. The radix can be 2, 8, 10 or 16. /// radix given. The radix can be 2, 8, 10, 16, or 36.
void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const { void toStringSigned(SmallVectorImpl<char> &Str, unsigned Radix = 10) const {
toString(Str, Radix, true, false); toString(Str, Radix, true, false);
} }

View File

@ -147,7 +147,53 @@ namespace llvm {
/// @} /// @}
}; };
/// @name ArrayRef Convenience constructors
/// @{
/// Construct an ArrayRef from a single element.
template<typename T>
ArrayRef<T> makeArrayRef(const T &OneElt) {
return OneElt;
}
/// Construct an ArrayRef from a pointer and length.
template<typename T>
ArrayRef<T> makeArrayRef(const T *data, size_t length) {
return ArrayRef<T>(data, length);
}
/// Construct an ArrayRef from a range.
template<typename T>
ArrayRef<T> makeArrayRef(const T *begin, const T *end) {
return ArrayRef<T>(begin, end);
}
/// Construct an ArrayRef from a SmallVector.
template <typename T>
ArrayRef<T> makeArrayRef(const SmallVectorImpl<T> &Vec) {
return Vec;
}
/// Construct an ArrayRef from a SmallVector.
template <typename T, unsigned N>
ArrayRef<T> makeArrayRef(const SmallVector<T, N> &Vec) {
return Vec;
}
/// Construct an ArrayRef from a std::vector.
template<typename T>
ArrayRef<T> makeArrayRef(const std::vector<T> &Vec) {
return Vec;
}
/// Construct an ArrayRef from a C array.
template<typename T, size_t N>
ArrayRef<T> makeArrayRef(const T (&Arr)[N]) {
return ArrayRef<T>(Arr);
}
/// @}
/// @name ArrayRef Comparison Operators /// @name ArrayRef Comparison Operators
/// @{ /// @{

View File

@ -540,6 +540,12 @@ class DenseMapIterator {
++Ptr; ++Ptr;
} }
}; };
template<typename KeyT, typename ValueT, typename KeyInfoT, typename ValueInfoT>
static inline size_t
capacity_in_bytes(const DenseMap<KeyT, ValueT, KeyInfoT, ValueInfoT> &X) {
return X.getMemorySize();
}
} // end namespace llvm } // end namespace llvm

View File

@ -51,7 +51,7 @@ struct DenseMapInfo<T*> {
template<> struct DenseMapInfo<char> { template<> struct DenseMapInfo<char> {
static inline char getEmptyKey() { return ~0; } static inline char getEmptyKey() { return ~0; }
static inline char getTombstoneKey() { return ~0 - 1; } static inline char getTombstoneKey() { return ~0 - 1; }
static unsigned getHashValue(const char& Val) { return Val * 37; } static unsigned getHashValue(const char& Val) { return Val * 37U; }
static bool isEqual(const char &LHS, const char &RHS) { static bool isEqual(const char &LHS, const char &RHS) {
return LHS == RHS; return LHS == RHS;
} }
@ -61,7 +61,7 @@ template<> struct DenseMapInfo<char> {
template<> struct DenseMapInfo<unsigned> { template<> struct DenseMapInfo<unsigned> {
static inline unsigned getEmptyKey() { return ~0; } static inline unsigned getEmptyKey() { return ~0; }
static inline unsigned getTombstoneKey() { return ~0U - 1; } static inline unsigned getTombstoneKey() { return ~0U - 1; }
static unsigned getHashValue(const unsigned& Val) { return Val * 37; } static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
static bool isEqual(const unsigned& LHS, const unsigned& RHS) { static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
return LHS == RHS; return LHS == RHS;
} }
@ -96,7 +96,7 @@ template<> struct DenseMapInfo<unsigned long long> {
template<> struct DenseMapInfo<int> { template<> struct DenseMapInfo<int> {
static inline int getEmptyKey() { return 0x7fffffff; } static inline int getEmptyKey() { return 0x7fffffff; }
static inline int getTombstoneKey() { return -0x7fffffff - 1; } static inline int getTombstoneKey() { return -0x7fffffff - 1; }
static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37); } static unsigned getHashValue(const int& Val) { return (unsigned)(Val * 37U); }
static bool isEqual(const int& LHS, const int& RHS) { static bool isEqual(const int& LHS, const int& RHS) {
return LHS == RHS; return LHS == RHS;
} }
@ -109,7 +109,7 @@ template<> struct DenseMapInfo<long> {
} }
static inline long getTombstoneKey() { return getEmptyKey() - 1L; } static inline long getTombstoneKey() { return getEmptyKey() - 1L; }
static unsigned getHashValue(const long& Val) { static unsigned getHashValue(const long& Val) {
return (unsigned)(Val * 37L); return (unsigned)(Val * 37UL);
} }
static bool isEqual(const long& LHS, const long& RHS) { static bool isEqual(const long& LHS, const long& RHS) {
return LHS == RHS; return LHS == RHS;
@ -121,7 +121,7 @@ template<> struct DenseMapInfo<long long> {
static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; } static inline long long getEmptyKey() { return 0x7fffffffffffffffLL; }
static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; } static inline long long getTombstoneKey() { return -0x7fffffffffffffffLL-1; }
static unsigned getHashValue(const long long& Val) { static unsigned getHashValue(const long long& Val) {
return (unsigned)(Val * 37LL); return (unsigned)(Val * 37ULL);
} }
static bool isEqual(const long long& LHS, static bool isEqual(const long long& LHS,
const long long& RHS) { const long long& RHS) {
@ -142,7 +142,7 @@ struct DenseMapInfo<std::pair<T, U> > {
} }
static inline Pair getTombstoneKey() { static inline Pair getTombstoneKey() {
return std::make_pair(FirstInfo::getTombstoneKey(), return std::make_pair(FirstInfo::getTombstoneKey(),
SecondInfo::getEmptyKey()); SecondInfo::getTombstoneKey());
} }
static unsigned getHashValue(const Pair& PairVal) { static unsigned getHashValue(const Pair& PairVal) {
uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32 uint64_t key = (uint64_t)FirstInfo::getHashValue(PairVal.first) << 32
@ -158,7 +158,7 @@ struct DenseMapInfo<std::pair<T, U> > {
return (unsigned)key; return (unsigned)key;
} }
static bool isEqual(const Pair &LHS, const Pair &RHS) { static bool isEqual(const Pair &LHS, const Pair &RHS) {
return FirstInfo::isEqual(LHS.first, RHS.first) && return FirstInfo::isEqual(LHS.first, RHS.first) &&
SecondInfo::isEqual(LHS.second, RHS.second); SecondInfo::isEqual(LHS.second, RHS.second);
} }
}; };

View File

@ -28,7 +28,7 @@ class DenseSet {
MapTy TheMap; MapTy TheMap;
public: public:
DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {} DenseSet(const DenseSet &Other) : TheMap(Other.TheMap) {}
explicit DenseSet(unsigned NumInitBuckets = 64) : TheMap(NumInitBuckets) {} explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {}
bool empty() const { return TheMap.empty(); } bool empty() const { return TheMap.empty(); }
unsigned size() const { return TheMap.size(); } unsigned size() const { return TheMap.size(); }

View File

@ -117,6 +117,10 @@ class ImmutableMap {
return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T); return ImmutableMap(Canonicalize ? F.getCanonicalTree(T): T);
} }
typename TreeTy::Factory *getTreeFactory() const {
return const_cast<typename TreeTy::Factory *>(&F);
}
private: private:
Factory(const Factory& RHS); // DO NOT IMPLEMENT Factory(const Factory& RHS); // DO NOT IMPLEMENT
void operator=(const Factory& RHS); // DO NOT IMPLEMENT void operator=(const Factory& RHS); // DO NOT IMPLEMENT
@ -256,6 +260,159 @@ class ImmutableMap {
} }
}; };
// NOTE: This will possibly become the new implementation of ImmutableMap some day.
template <typename KeyT, typename ValT,
typename ValInfo = ImutKeyValueInfo<KeyT,ValT> >
class ImmutableMapRef {
public:
typedef typename ValInfo::value_type value_type;
typedef typename ValInfo::value_type_ref value_type_ref;
typedef typename ValInfo::key_type key_type;
typedef typename ValInfo::key_type_ref key_type_ref;
typedef typename ValInfo::data_type data_type;
typedef typename ValInfo::data_type_ref data_type_ref;
typedef ImutAVLTree<ValInfo> TreeTy;
typedef typename TreeTy::Factory FactoryTy;
protected:
TreeTy *Root;
FactoryTy *Factory;
public:
/// Constructs a map from a pointer to a tree root. In general one
/// should use a Factory object to create maps instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableMapRef(const TreeTy* R, FactoryTy *F)
: Root(const_cast<TreeTy*>(R)),
Factory(F) {
if (Root) { Root->retain(); }
}
ImmutableMapRef(const ImmutableMapRef &X)
: Root(X.Root),
Factory(X.Factory) {
if (Root) { Root->retain(); }
}
ImmutableMapRef &operator=(const ImmutableMapRef &X) {
if (Root != X.Root) {
if (X.Root)
X.Root->retain();
if (Root)
Root->release();
Root = X.Root;
Factory = X.Factory;
}
return *this;
}
~ImmutableMapRef() {
if (Root)
Root->release();
}
static inline ImmutableMapRef getEmptyMap(FactoryTy *F) {
return ImmutableMapRef(0, F);
}
ImmutableMapRef add(key_type_ref K, data_type_ref D) {
TreeTy *NewT = Factory->add(Root, std::pair<key_type, data_type>(K, D));
return ImmutableMapRef(NewT, Factory);
}
ImmutableMapRef remove(key_type_ref K) {
TreeTy *NewT = Factory->remove(Root, K);
return ImmutableMapRef(NewT, Factory);
}
bool contains(key_type_ref K) const {
return Root ? Root->contains(K) : false;
}
ImmutableMap<KeyT, ValT> asImmutableMap() const {
return ImmutableMap<KeyT, ValT>(Factory->getCanonicalTree(Root));
}
bool operator==(const ImmutableMapRef &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}
bool operator!=(const ImmutableMapRef &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}
bool isEmpty() const { return !Root; }
//===--------------------------------------------------===//
// For testing.
//===--------------------------------------------------===//
void verify() const { if (Root) Root->verify(); }
//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator() {}
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableMapRef;
public:
value_type_ref operator*() const { return itr->getValue(); }
value_type* operator->() const { return &itr->getValue(); }
key_type_ref getKey() const { return itr->getValue().first; }
data_type_ref getData() const { return itr->getValue().second; }
iterator& operator++() { ++itr; return *this; }
iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
iterator& operator--() { --itr; return *this; }
iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
};
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
data_type* lookup(key_type_ref K) const {
if (Root) {
TreeTy* T = Root->find(K);
if (T) return &T->getValue().second;
}
return 0;
}
/// getMaxElement - Returns the <key,value> pair in the ImmutableMap for
/// which key is the highest in the ordering of keys in the map. This
/// method returns NULL if the map is empty.
value_type* getMaxElement() const {
return Root ? &(Root->getMaxElement()->getValue()) : 0;
}
//===--------------------------------------------------===//
// Utility methods.
//===--------------------------------------------------===//
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
static inline void Profile(FoldingSetNodeID& ID, const ImmutableMapRef &M) {
ID.AddPointer(M.Root);
}
inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID, *this);
}
};
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -997,6 +997,10 @@ class ImmutableSet {
BumpPtrAllocator& getAllocator() { return F.getAllocator(); } BumpPtrAllocator& getAllocator() { return F.getAllocator(); }
typename TreeTy::Factory *getTreeFactory() const {
return const_cast<typename TreeTy::Factory *>(&F);
}
private: private:
Factory(const Factory& RHS); // DO NOT IMPLEMENT Factory(const Factory& RHS); // DO NOT IMPLEMENT
void operator=(const Factory& RHS); // DO NOT IMPLEMENT void operator=(const Factory& RHS); // DO NOT IMPLEMENT
@ -1021,6 +1025,10 @@ class ImmutableSet {
if (Root) { Root->retain(); } if (Root) { Root->retain(); }
return Root; return Root;
} }
TreeTy *getRootWithoutRetain() const {
return Root;
}
/// isEmpty - Return true if the set contains no elements. /// isEmpty - Return true if the set contains no elements.
bool isEmpty() const { return !Root; } bool isEmpty() const { return !Root; }
@ -1078,6 +1086,132 @@ class ImmutableSet {
void validateTree() const { if (Root) Root->validateTree(); } void validateTree() const { if (Root) Root->validateTree(); }
}; };
// NOTE: This may some day replace the current ImmutableSet.
template <typename ValT, typename ValInfo = ImutContainerInfo<ValT> >
class ImmutableSetRef {
public:
typedef typename ValInfo::value_type value_type;
typedef typename ValInfo::value_type_ref value_type_ref;
typedef ImutAVLTree<ValInfo> TreeTy;
typedef typename TreeTy::Factory FactoryTy;
private:
TreeTy *Root;
FactoryTy *Factory;
public:
/// Constructs a set from a pointer to a tree root. In general one
/// should use a Factory object to create sets instead of directly
/// invoking the constructor, but there are cases where make this
/// constructor public is useful.
explicit ImmutableSetRef(TreeTy* R, FactoryTy *F)
: Root(R),
Factory(F) {
if (Root) { Root->retain(); }
}
ImmutableSetRef(const ImmutableSetRef &X)
: Root(X.Root),
Factory(X.Factory) {
if (Root) { Root->retain(); }
}
ImmutableSetRef &operator=(const ImmutableSetRef &X) {
if (Root != X.Root) {
if (X.Root) { X.Root->retain(); }
if (Root) { Root->release(); }
Root = X.Root;
Factory = X.Factory;
}
return *this;
}
~ImmutableSetRef() {
if (Root) { Root->release(); }
}
static inline ImmutableSetRef getEmptySet(FactoryTy *F) {
return ImmutableSetRef(0, F);
}
ImmutableSetRef add(value_type_ref V) {
return ImmutableSetRef(Factory->add(Root, V), Factory);
}
ImmutableSetRef remove(value_type_ref V) {
return ImmutableSetRef(Factory->remove(Root, V), Factory);
}
/// Returns true if the set contains the specified value.
bool contains(value_type_ref V) const {
return Root ? Root->contains(V) : false;
}
ImmutableSet<ValT> asImmutableSet(bool canonicalize = true) const {
return ImmutableSet<ValT>(canonicalize ?
Factory->getCanonicalTree(Root) : Root);
}
TreeTy *getRootWithoutRetain() const {
return Root;
}
bool operator==(const ImmutableSetRef &RHS) const {
return Root && RHS.Root ? Root->isEqual(*RHS.Root) : Root == RHS.Root;
}
bool operator!=(const ImmutableSetRef &RHS) const {
return Root && RHS.Root ? Root->isNotEqual(*RHS.Root) : Root != RHS.Root;
}
/// isEmpty - Return true if the set contains no elements.
bool isEmpty() const { return !Root; }
/// isSingleton - Return true if the set contains exactly one element.
/// This method runs in constant time.
bool isSingleton() const { return getHeight() == 1; }
//===--------------------------------------------------===//
// Iterators.
//===--------------------------------------------------===//
class iterator {
typename TreeTy::iterator itr;
iterator(TreeTy* t) : itr(t) {}
friend class ImmutableSetRef<ValT,ValInfo>;
public:
iterator() {}
inline value_type_ref operator*() const { return itr->getValue(); }
inline iterator& operator++() { ++itr; return *this; }
inline iterator operator++(int) { iterator tmp(*this); ++itr; return tmp; }
inline iterator& operator--() { --itr; return *this; }
inline iterator operator--(int) { iterator tmp(*this); --itr; return tmp; }
inline bool operator==(const iterator& RHS) const { return RHS.itr == itr; }
inline bool operator!=(const iterator& RHS) const { return RHS.itr != itr; }
inline value_type *operator->() const { return &(operator*()); }
};
iterator begin() const { return iterator(Root); }
iterator end() const { return iterator(); }
//===--------------------------------------------------===//
// Utility methods.
//===--------------------------------------------------===//
unsigned getHeight() const { return Root ? Root->getHeight() : 0; }
static inline void Profile(FoldingSetNodeID& ID, const ImmutableSetRef& S) {
ID.AddPointer(S.Root);
}
inline void Profile(FoldingSetNodeID& ID) const {
return Profile(ID,*this);
}
//===--------------------------------------------------===//
// For testing.
//===--------------------------------------------------===//
void validateTree() const { if (Root) Root->validateTree(); }
};
} // end namespace llvm } // end namespace llvm

View File

@ -1335,6 +1335,9 @@ class IntervalMap<KeyT, ValT, N, Traits>::const_iterator :
/// valid - Return true if the current position is valid, false for end(). /// valid - Return true if the current position is valid, false for end().
bool valid() const { return path.valid(); } bool valid() const { return path.valid(); }
/// atBegin - Return true if the current position is the first map entry.
bool atBegin() const { return path.atBegin(); }
/// start - Return the beginning of the current interval. /// start - Return the beginning of the current interval.
const KeyT &start() const { return unsafeStart(); } const KeyT &start() const { return unsafeStart(); }

View File

@ -108,7 +108,11 @@ namespace llvm {
/// isNull - Return true if the pointer held in the union is null, /// isNull - Return true if the pointer held in the union is null,
/// regardless of which type it is. /// regardless of which type it is.
bool isNull() const { return Val.getPointer() == 0; } bool isNull() const {
// Convert from the void* to one of the pointer types, to make sure that
// we recursively strip off low bits if we have a nested PointerUnion.
return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
}
operator bool() const { return !isNull(); } operator bool() const { return !isNull(); }
/// is<T>() return true if the Union currently holds the type matching T. /// is<T>() return true if the Union currently holds the type matching T.

View File

@ -29,6 +29,14 @@ class po_iterator_storage {
SetType Visited; SetType Visited;
}; };
/// DFSetTraits - Allow the SetType used to record depth-first search results to
/// optionally record node postorder.
template<class SetType>
struct DFSetTraits {
static void finishPostorder(
typename SetType::iterator::value_type, SetType &) {}
};
template<class SetType> template<class SetType>
class po_iterator_storage<SetType, true> { class po_iterator_storage<SetType, true> {
public: public:
@ -109,6 +117,8 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
inline NodeType *operator->() const { return operator*(); } inline NodeType *operator->() const { return operator*(); }
inline _Self& operator++() { // Preincrement inline _Self& operator++() { // Preincrement
DFSetTraits<SetType>::finishPostorder(VisitStack.back().first,
this->Visited);
VisitStack.pop_back(); VisitStack.pop_back();
if (!VisitStack.empty()) if (!VisitStack.empty())
traverseChild(); traverseChild();

View File

@ -1,4 +1,4 @@
//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// //===---- ADT/SCCIterator.h - Strongly Connected Comp. Iter. ----*- C++ -*-===//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -87,7 +87,7 @@ class scc_iterator
DFSVisitOne(childN); DFSVisitOne(childN);
continue; continue;
} }
unsigned childNum = nodeVisitNumbers[childN]; unsigned childNum = nodeVisitNumbers[childN];
if (MinVisitNumStack.back() > childNum) if (MinVisitNumStack.back() > childNum)
MinVisitNumStack.back() = childNum; MinVisitNumStack.back() = childNum;
@ -114,7 +114,7 @@ class scc_iterator
if (minVisitNum != nodeVisitNumbers[visitingN]) if (minVisitNum != nodeVisitNumbers[visitingN])
continue; continue;
// A full SCC is on the SCCNodeStack! It includes all nodes below // A full SCC is on the SCCNodeStack! It includes all nodes below
// visitingN on the stack. Copy those nodes to CurrentSCC, // visitingN on the stack. Copy those nodes to CurrentSCC,
// reset their minVisit values, and return (this suspends // reset their minVisit values, and return (this suspends
@ -139,7 +139,7 @@ class scc_iterator
// Provide static "constructors"... // Provide static "constructors"...
static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));} static inline _Self begin(const GraphT &G){return _Self(GT::getEntryNode(G));}
static inline _Self end (const GraphT &G) { return _Self(); } static inline _Self end (const GraphT &) { return _Self(); }
// Direct loop termination test: I.isAtEnd() is more efficient than I == end() // Direct loop termination test: I.isAtEnd() is more efficient than I == end()
inline bool isAtEnd() const { inline bool isAtEnd() const {
@ -183,7 +183,7 @@ class scc_iterator
return true; return true;
return false; return false;
} }
/// ReplaceNode - This informs the scc_iterator that the specified Old node /// ReplaceNode - This informs the scc_iterator that the specified Old node
/// has been deleted, and New is to be used in its place. /// has been deleted, and New is to be used in its place.
void ReplaceNode(NodeType *Old, NodeType *New) { void ReplaceNode(NodeType *Old, NodeType *New) {

View File

@ -186,25 +186,21 @@ inline ItTy prior(ItTy it)
// // do stuff // // do stuff
// else // else
// // do other stuff // // do other stuff
template <typename T1, typename T2>
struct tier {
typedef T1 &first_type;
typedef T2 &second_type;
namespace first_type first;
{ second_type second;
template <typename T1, typename T2>
struct tier {
typedef T1 &first_type;
typedef T2 &second_type;
first_type first; tier(first_type f, second_type s) : first(f), second(s) { }
second_type second; tier& operator=(const std::pair<T1, T2>& p) {
first = p.first;
tier(first_type f, second_type s) : first(f), second(s) { } second = p.second;
tier& operator=(const std::pair<T1, T2>& p) { return *this;
first = p.first; }
second = p.second; };
return *this;
}
};
}
template <typename T1, typename T2> template <typename T1, typename T2>
inline tier<T1, T2> tie(T1& f, T2& s) { inline tier<T1, T2> tie(T1& f, T2& s) {

View File

@ -78,21 +78,21 @@ class SmallVectorBase {
return BeginX == static_cast<const void*>(&FirstEl); return BeginX == static_cast<const void*>(&FirstEl);
} }
/// size_in_bytes - This returns size()*sizeof(T).
size_t size_in_bytes() const {
return size_t((char*)EndX - (char*)BeginX);
}
/// capacity_in_bytes - This returns capacity()*sizeof(T).
size_t capacity_in_bytes() const {
return size_t((char*)CapacityX - (char*)BeginX);
}
/// grow_pod - This is an implementation of the grow() method which only works /// grow_pod - This is an implementation of the grow() method which only works
/// on POD-like data types and is out of line to reduce code duplication. /// on POD-like data types and is out of line to reduce code duplication.
void grow_pod(size_t MinSizeInBytes, size_t TSize); void grow_pod(size_t MinSizeInBytes, size_t TSize);
public: public:
/// size_in_bytes - This returns size()*sizeof(T).
size_t size_in_bytes() const {
return size_t((char*)EndX - (char*)BeginX);
}
/// capacity_in_bytes - This returns capacity()*sizeof(T).
size_t capacity_in_bytes() const {
return size_t((char*)CapacityX - (char*)BeginX);
}
bool empty() const { return BeginX == EndX; } bool empty() const { return BeginX == EndX; }
}; };
@ -738,6 +738,11 @@ class SmallVector<T,0> : public SmallVectorImpl<T> {
}; };
template<typename T, unsigned N>
static inline size_t capacity_in_bytes(const SmallVector<T, N> &X) {
return X.capacity_in_bytes();
}
} // End llvm namespace } // End llvm namespace
namespace std { namespace std {

View File

@ -54,7 +54,7 @@ class Statistic {
Value = Val; Value = Val;
return init(); return init();
} }
const Statistic &operator++() { const Statistic &operator++() {
// FIXME: This function and all those that follow carefully use an // FIXME: This function and all those that follow carefully use an
// atomic operation to update the value safely in the presence of // atomic operation to update the value safely in the presence of
@ -63,41 +63,43 @@ class Statistic {
sys::AtomicIncrement(&Value); sys::AtomicIncrement(&Value);
return init(); return init();
} }
unsigned operator++(int) { unsigned operator++(int) {
init(); init();
unsigned OldValue = Value; unsigned OldValue = Value;
sys::AtomicIncrement(&Value); sys::AtomicIncrement(&Value);
return OldValue; return OldValue;
} }
const Statistic &operator--() { const Statistic &operator--() {
sys::AtomicDecrement(&Value); sys::AtomicDecrement(&Value);
return init(); return init();
} }
unsigned operator--(int) { unsigned operator--(int) {
init(); init();
unsigned OldValue = Value; unsigned OldValue = Value;
sys::AtomicDecrement(&Value); sys::AtomicDecrement(&Value);
return OldValue; return OldValue;
} }
const Statistic &operator+=(const unsigned &V) { const Statistic &operator+=(const unsigned &V) {
if (!V) return *this;
sys::AtomicAdd(&Value, V); sys::AtomicAdd(&Value, V);
return init(); return init();
} }
const Statistic &operator-=(const unsigned &V) { const Statistic &operator-=(const unsigned &V) {
if (!V) return *this;
sys::AtomicAdd(&Value, -V); sys::AtomicAdd(&Value, -V);
return init(); return init();
} }
const Statistic &operator*=(const unsigned &V) { const Statistic &operator*=(const unsigned &V) {
sys::AtomicMul(&Value, V); sys::AtomicMul(&Value, V);
return init(); return init();
} }
const Statistic &operator/=(const unsigned &V) { const Statistic &operator/=(const unsigned &V) {
sys::AtomicDiv(&Value, V); sys::AtomicDiv(&Value, V);
return init(); return init();

View File

@ -16,6 +16,7 @@
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
#include "llvm/ADT/APFloat.h" #include "llvm/ADT/APFloat.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringRef.h"
#include <cctype> #include <cctype>
#include <cstdio> #include <cstdio>

View File

@ -0,0 +1,133 @@
//===- llvm/ADT/TinyPtrVector.h - 'Normally tiny' vectors -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_TINYPTRVECTOR_H
#define LLVM_ADT_TINYPTRVECTOR_H
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/PointerUnion.h"
namespace llvm {
/// TinyPtrVector - This class is specialized for cases where there are
/// normally 0 or 1 element in a vector, but is general enough to go beyond that
/// when required.
///
/// NOTE: This container doesn't allow you to store a null pointer into it.
///
template <typename EltTy>
class TinyPtrVector {
public:
typedef llvm::SmallVector<EltTy, 4> VecTy;
llvm::PointerUnion<EltTy, VecTy*> Val;
TinyPtrVector() {}
TinyPtrVector(const TinyPtrVector &RHS) : Val(RHS.Val) {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
Val = new VecTy(*V);
}
~TinyPtrVector() {
if (VecTy *V = Val.template dyn_cast<VecTy*>())
delete V;
}
bool empty() const {
// This vector can be empty if it contains no element, or if it
// contains a pointer to an empty vector.
if (Val.isNull()) return true;
if (VecTy *Vec = Val.template dyn_cast<VecTy*>())
return Vec->empty();
return false;
}
unsigned size() const {
if (empty())
return 0;
if (Val.template is<EltTy>())
return 1;
return Val.template get<VecTy*>()->size();
}
typedef const EltTy *iterator;
iterator begin() const {
if (empty())
return 0;
if (Val.template is<EltTy>())
return Val.template getAddrOf<EltTy>();
return Val.template get<VecTy *>()->begin();
}
iterator end() const {
if (empty())
return 0;
if (Val.template is<EltTy>())
return begin() + 1;
return Val.template get<VecTy *>()->end();
}
EltTy operator[](unsigned i) const {
assert(!Val.isNull() && "can't index into an empty vector");
if (EltTy V = Val.template dyn_cast<EltTy>()) {
assert(i == 0 && "tinyvector index out of range");
return V;
}
assert(i < Val.template get<VecTy*>()->size() &&
"tinyvector index out of range");
return (*Val.template get<VecTy*>())[i];
}
EltTy front() const {
assert(!empty() && "vector empty");
if (EltTy V = Val.template dyn_cast<EltTy>())
return V;
return Val.template get<VecTy*>()->front();
}
void push_back(EltTy NewVal) {
assert(NewVal != 0 && "Can't add a null value");
// If we have nothing, add something.
if (Val.isNull()) {
Val = NewVal;
return;
}
// If we have a single value, convert to a vector.
if (EltTy V = Val.template dyn_cast<EltTy>()) {
Val = new VecTy();
Val.template get<VecTy*>()->push_back(V);
}
// Add the new value, we know we have a vector.
Val.template get<VecTy*>()->push_back(NewVal);
}
void clear() {
// If we have a single value, convert to empty.
if (Val.template is<EltTy>()) {
Val = (EltTy)0;
} else if (VecTy *Vec = Val.template dyn_cast<VecTy*>()) {
// If we have a vector form, just clear it.
Vec->clear();
}
// Otherwise, we're already empty.
}
private:
void operator=(const TinyPtrVector&); // NOT IMPLEMENTED YET.
};
} // end namespace llvm
#endif

View File

@ -10,8 +10,7 @@
#ifndef LLVM_ADT_TRIPLE_H #ifndef LLVM_ADT_TRIPLE_H
#define LLVM_ADT_TRIPLE_H #define LLVM_ADT_TRIPLE_H
#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h"
#include <string>
// Some system headers or GCC predefined macros conflict with identifiers in // Some system headers or GCC predefined macros conflict with identifiers in
// this file. Undefine them here. // this file. Undefine them here.
@ -19,8 +18,6 @@
#undef sparc #undef sparc
namespace llvm { namespace llvm {
class StringRef;
class Twine;
/// Triple - Helper class for working with target triples. /// Triple - Helper class for working with target triples.
/// ///
@ -52,6 +49,8 @@ class Triple {
cellspu, // CellSPU: spu, cellspu cellspu, // CellSPU: spu, cellspu
mips, // MIPS: mips, mipsallegrex mips, // MIPS: mips, mipsallegrex
mipsel, // MIPSEL: mipsel, mipsallegrexel, psp mipsel, // MIPSEL: mipsel, mipsallegrexel, psp
mips64, // MIPS64: mips64
mips64el,// MIPS64EL: mips64el
msp430, // MSP430: msp430 msp430, // MSP430: msp430
ppc, // PPC: powerpc ppc, // PPC: powerpc
ppc64, // PPC64: powerpc64, ppu ppc64, // PPC64: powerpc64, ppu
@ -66,6 +65,8 @@ class Triple {
mblaze, // MBlaze: mblaze mblaze, // MBlaze: mblaze
ptx32, // PTX: ptx (32-bit) ptx32, // PTX: ptx (32-bit)
ptx64, // PTX: ptx (64-bit) ptx64, // PTX: ptx (64-bit)
le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten)
amdil, // amdil: amd IL
InvalidArch InvalidArch
}; };
@ -85,6 +86,7 @@ class Triple {
DragonFly, DragonFly,
FreeBSD, FreeBSD,
IOS, IOS,
KFreeBSD,
Linux, Linux,
Lv2, // PS3 Lv2, // PS3
MacOSX, MacOSX,
@ -96,7 +98,8 @@ class Triple {
Win32, Win32,
Haiku, Haiku,
Minix, Minix,
RTEMS RTEMS,
NativeClient
}; };
enum EnvironmentType { enum EnvironmentType {
UnknownEnvironment, UnknownEnvironment,
@ -134,24 +137,16 @@ class Triple {
/// @{ /// @{
Triple() : Data(), Arch(InvalidArch) {} Triple() : Data(), Arch(InvalidArch) {}
explicit Triple(StringRef Str) : Data(Str), Arch(InvalidArch) {} explicit Triple(const Twine &Str) : Data(Str.str()), Arch(InvalidArch) {}
explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr) Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr)
: Data(ArchStr), Arch(InvalidArch) { : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr).str()),
Data += '-'; Arch(InvalidArch) {
Data += VendorStr;
Data += '-';
Data += OSStr;
} }
explicit Triple(StringRef ArchStr, StringRef VendorStr, StringRef OSStr, Triple(const Twine &ArchStr, const Twine &VendorStr, const Twine &OSStr,
StringRef EnvironmentStr) const Twine &EnvironmentStr)
: Data(ArchStr), Arch(InvalidArch) { : Data((ArchStr + Twine('-') + VendorStr + Twine('-') + OSStr + Twine('-') +
Data += '-'; EnvironmentStr).str()), Arch(InvalidArch) {
Data += VendorStr;
Data += '-';
Data += OSStr;
Data += '-';
Data += EnvironmentStr;
} }
/// @} /// @}

View File

@ -99,6 +99,9 @@ namespace llvm {
/// A pointer to a StringRef instance. /// A pointer to a StringRef instance.
StringRefKind, StringRefKind,
/// A char value reinterpreted as a pointer, to render as a character.
CharKind,
/// An unsigned int value reinterpreted as a pointer, to render as an /// An unsigned int value reinterpreted as a pointer, to render as an
/// unsigned decimal integer. /// unsigned decimal integer.
DecUIKind, DecUIKind,
@ -126,13 +129,31 @@ namespace llvm {
UHexKind UHexKind
}; };
union Child
{
const Twine *twine;
const char *cString;
const std::string *stdString;
const StringRef *stringRef;
char character;
unsigned int decUI;
int decI;
const unsigned long *decUL;
const long *decL;
const unsigned long long *decULL;
const long long *decLL;
const uint64_t *uHex;
};
private: private:
/// LHS - The prefix in the concatenation, which may be uninitialized for /// LHS - The prefix in the concatenation, which may be uninitialized for
/// Null or Empty kinds. /// Null or Empty kinds.
const void *LHS; Child LHS;
/// RHS - The suffix in the concatenation, which may be uninitialized for /// RHS - The suffix in the concatenation, which may be uninitialized for
/// Null or Empty kinds. /// Null or Empty kinds.
const void *RHS; Child RHS;
// enums stored as unsigned chars to save on space while some compilers
// don't support specifying the backing type for an enum
/// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). /// LHSKind - The NodeKind of the left hand side, \see getLHSKind().
unsigned char LHSKind; unsigned char LHSKind;
/// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). /// RHSKind - The NodeKind of the left hand side, \see getLHSKind().
@ -147,13 +168,15 @@ namespace llvm {
/// Construct a binary twine. /// Construct a binary twine.
explicit Twine(const Twine &_LHS, const Twine &_RHS) explicit Twine(const Twine &_LHS, const Twine &_RHS)
: LHS(&_LHS), RHS(&_RHS), LHSKind(TwineKind), RHSKind(TwineKind) { : LHSKind(TwineKind), RHSKind(TwineKind) {
LHS.twine = &_LHS;
RHS.twine = &_RHS;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct a twine from explicit values. /// Construct a twine from explicit values.
explicit Twine(const void *_LHS, NodeKind _LHSKind, explicit Twine(Child _LHS, NodeKind _LHSKind,
const void *_RHS, NodeKind _RHSKind) Child _RHS, NodeKind _RHSKind)
: LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) { : LHS(_LHS), RHS(_RHS), LHSKind(_LHSKind), RHSKind(_RHSKind) {
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
@ -200,10 +223,10 @@ namespace llvm {
// A twine child should always be binary. // A twine child should always be binary.
if (getLHSKind() == TwineKind && if (getLHSKind() == TwineKind &&
!static_cast<const Twine*>(LHS)->isBinary()) !LHS.twine->isBinary())
return false; return false;
if (getRHSKind() == TwineKind && if (getRHSKind() == TwineKind &&
!static_cast<const Twine*>(RHS)->isBinary()) !RHS.twine->isBinary())
return false; return false;
return true; return true;
@ -216,10 +239,10 @@ namespace llvm {
NodeKind getRHSKind() const { return (NodeKind) RHSKind; } NodeKind getRHSKind() const { return (NodeKind) RHSKind; }
/// printOneChild - Print one child from a twine. /// printOneChild - Print one child from a twine.
void printOneChild(raw_ostream &OS, const void *Ptr, NodeKind Kind) const; void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const;
/// printOneChildRepr - Print the representation of one child from a twine. /// printOneChildRepr - Print the representation of one child from a twine.
void printOneChildRepr(raw_ostream &OS, const void *Ptr, void printOneChildRepr(raw_ostream &OS, Child Ptr,
NodeKind Kind) const; NodeKind Kind) const;
public: public:
@ -239,7 +262,7 @@ namespace llvm {
/*implicit*/ Twine(const char *Str) /*implicit*/ Twine(const char *Str)
: RHSKind(EmptyKind) { : RHSKind(EmptyKind) {
if (Str[0] != '\0') { if (Str[0] != '\0') {
LHS = Str; LHS.cString = Str;
LHSKind = CStringKind; LHSKind = CStringKind;
} else } else
LHSKind = EmptyKind; LHSKind = EmptyKind;
@ -249,44 +272,70 @@ namespace llvm {
/// Construct from an std::string. /// Construct from an std::string.
/*implicit*/ Twine(const std::string &Str) /*implicit*/ Twine(const std::string &Str)
: LHS(&Str), LHSKind(StdStringKind), RHSKind(EmptyKind) { : LHSKind(StdStringKind), RHSKind(EmptyKind) {
LHS.stdString = &Str;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct from a StringRef. /// Construct from a StringRef.
/*implicit*/ Twine(const StringRef &Str) /*implicit*/ Twine(const StringRef &Str)
: LHS(&Str), LHSKind(StringRefKind), RHSKind(EmptyKind) { : LHSKind(StringRefKind), RHSKind(EmptyKind) {
LHS.stringRef = &Str;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct from a char.
explicit Twine(char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) {
LHS.character = Val;
}
/// Construct from a signed char.
explicit Twine(signed char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) {
LHS.character = static_cast<char>(Val);
}
/// Construct from an unsigned char.
explicit Twine(unsigned char Val)
: LHSKind(CharKind), RHSKind(EmptyKind) {
LHS.character = static_cast<char>(Val);
}
/// Construct a twine to print \arg Val as an unsigned decimal integer. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(unsigned Val) explicit Twine(unsigned Val)
: LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { : LHSKind(DecUIKind), RHSKind(EmptyKind) {
LHS.decUI = Val;
} }
/// Construct a twine to print \arg Val as a signed decimal integer. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(int Val) explicit Twine(int Val)
: LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { : LHSKind(DecIKind), RHSKind(EmptyKind) {
LHS.decI = Val;
} }
/// Construct a twine to print \arg Val as an unsigned decimal integer. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long &Val) explicit Twine(const unsigned long &Val)
: LHS(&Val), LHSKind(DecULKind), RHSKind(EmptyKind) { : LHSKind(DecULKind), RHSKind(EmptyKind) {
LHS.decUL = &Val;
} }
/// Construct a twine to print \arg Val as a signed decimal integer. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long &Val) explicit Twine(const long &Val)
: LHS(&Val), LHSKind(DecLKind), RHSKind(EmptyKind) { : LHSKind(DecLKind), RHSKind(EmptyKind) {
LHS.decL = &Val;
} }
/// Construct a twine to print \arg Val as an unsigned decimal integer. /// Construct a twine to print \arg Val as an unsigned decimal integer.
explicit Twine(const unsigned long long &Val) explicit Twine(const unsigned long long &Val)
: LHS(&Val), LHSKind(DecULLKind), RHSKind(EmptyKind) { : LHSKind(DecULLKind), RHSKind(EmptyKind) {
LHS.decULL = &Val;
} }
/// Construct a twine to print \arg Val as a signed decimal integer. /// Construct a twine to print \arg Val as a signed decimal integer.
explicit Twine(const long long &Val) explicit Twine(const long long &Val)
: LHS(&Val), LHSKind(DecLLKind), RHSKind(EmptyKind) { : LHSKind(DecLLKind), RHSKind(EmptyKind) {
LHS.decLL = &Val;
} }
// FIXME: Unfortunately, to make sure this is as efficient as possible we // FIXME: Unfortunately, to make sure this is as efficient as possible we
@ -296,13 +345,17 @@ namespace llvm {
/// Construct as the concatenation of a C string and a StringRef. /// Construct as the concatenation of a C string and a StringRef.
/*implicit*/ Twine(const char *_LHS, const StringRef &_RHS) /*implicit*/ Twine(const char *_LHS, const StringRef &_RHS)
: LHS(_LHS), RHS(&_RHS), LHSKind(CStringKind), RHSKind(StringRefKind) { : LHSKind(CStringKind), RHSKind(StringRefKind) {
LHS.cString = _LHS;
RHS.stringRef = &_RHS;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
/// Construct as the concatenation of a StringRef and a C string. /// Construct as the concatenation of a StringRef and a C string.
/*implicit*/ Twine(const StringRef &_LHS, const char *_RHS) /*implicit*/ Twine(const StringRef &_LHS, const char *_RHS)
: LHS(&_LHS), RHS(_RHS), LHSKind(StringRefKind), RHSKind(CStringKind) { : LHSKind(StringRefKind), RHSKind(CStringKind) {
LHS.stringRef = &_LHS;
RHS.cString = _RHS;
assert(isValid() && "Invalid twine!"); assert(isValid() && "Invalid twine!");
} }
@ -318,7 +371,10 @@ namespace llvm {
// Construct a twine to print \arg Val as an unsigned hexadecimal integer. // Construct a twine to print \arg Val as an unsigned hexadecimal integer.
static Twine utohexstr(const uint64_t &Val) { static Twine utohexstr(const uint64_t &Val) {
return Twine(&Val, UHexKind, 0, EmptyKind); Child LHS, RHS;
LHS.uHex = &Val;
RHS.twine = 0;
return Twine(LHS, UHexKind, RHS, EmptyKind);
} }
/// @} /// @}
@ -371,9 +427,9 @@ namespace llvm {
switch (getLHSKind()) { switch (getLHSKind()) {
default: assert(0 && "Out of sync with isSingleStringRef"); default: assert(0 && "Out of sync with isSingleStringRef");
case EmptyKind: return StringRef(); case EmptyKind: return StringRef();
case CStringKind: return StringRef((const char*)LHS); case CStringKind: return StringRef(LHS.cString);
case StdStringKind: return StringRef(*(const std::string*)LHS); case StdStringKind: return StringRef(*LHS.stdString);
case StringRefKind: return *(const StringRef*)LHS; case StringRefKind: return *LHS.stringRef;
} }
} }
@ -422,7 +478,9 @@ namespace llvm {
// Otherwise we need to create a new node, taking care to fold in unary // Otherwise we need to create a new node, taking care to fold in unary
// twines. // twines.
const void *NewLHS = this, *NewRHS = &Suffix; Child NewLHS, NewRHS;
NewLHS.twine = this;
NewRHS.twine = &Suffix;
NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind; NodeKind NewLHSKind = TwineKind, NewRHSKind = TwineKind;
if (isUnary()) { if (isUnary()) {
NewLHS = LHS; NewLHS = LHS;

View File

@ -88,7 +88,7 @@ class AliasAnalysis {
/// getTypeStoreSize - Return the TargetData store size for the given type, /// getTypeStoreSize - Return the TargetData store size for the given type,
/// if known, or a conservative value otherwise. /// if known, or a conservative value otherwise.
/// ///
uint64_t getTypeStoreSize(const Type *Ty); uint64_t getTypeStoreSize(Type *Ty);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// Alias Queries... /// Alias Queries...
@ -136,6 +136,8 @@ class AliasAnalysis {
Location getLocation(const LoadInst *LI); Location getLocation(const LoadInst *LI);
Location getLocation(const StoreInst *SI); Location getLocation(const StoreInst *SI);
Location getLocation(const VAArgInst *VI); Location getLocation(const VAArgInst *VI);
Location getLocation(const AtomicCmpXchgInst *CXI);
Location getLocation(const AtomicRMWInst *RMWI);
static Location getLocationForSource(const MemTransferInst *MTI); static Location getLocationForSource(const MemTransferInst *MTI);
static Location getLocationForDest(const MemIntrinsic *MI); static Location getLocationForDest(const MemIntrinsic *MI);
@ -341,6 +343,11 @@ class AliasAnalysis {
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc); case Instruction::Store: return getModRefInfo((const StoreInst*)I, Loc);
case Instruction::Fence: return getModRefInfo((const FenceInst*)I, Loc);
case Instruction::AtomicCmpXchg:
return getModRefInfo((const AtomicCmpXchgInst*)I, Loc);
case Instruction::AtomicRMW:
return getModRefInfo((const AtomicRMWInst*)I, Loc);
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
default: return NoModRef; default: return NoModRef;
@ -406,6 +413,39 @@ class AliasAnalysis {
return getModRefInfo(S, Location(P, Size)); return getModRefInfo(S, Location(P, Size));
} }
/// getModRefInfo (for fences) - Return whether information about whether
/// a particular store modifies or reads the specified memory location.
ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
// Conservatively correct. (We could possibly be a bit smarter if
// Loc is a alloca that doesn't escape.)
return ModRef;
}
/// getModRefInfo (for fences) - A convenience wrapper.
ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
return getModRefInfo(S, Location(P, Size));
}
/// getModRefInfo (for cmpxchges) - Return whether information about whether
/// a particular cmpxchg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc);
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX,
const Value *P, unsigned Size) {
return getModRefInfo(CX, Location(P, Size));
}
/// getModRefInfo (for atomicrmws) - Return whether information about whether
/// a particular atomicrmw modifies or reads the specified memory location.
ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc);
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
ModRefResult getModRefInfo(const AtomicRMWInst *RMW,
const Value *P, unsigned Size) {
return getModRefInfo(RMW, Location(P, Size));
}
/// getModRefInfo (for va_args) - Return whether information about whether /// getModRefInfo (for va_args) - Return whether information about whether
/// a particular va_arg modifies or reads the specified memory location. /// a particular va_arg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc); ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);

View File

@ -111,8 +111,8 @@ class AliasSet : public ilist_node<AliasSet> {
AliasSet *Forward; // Forwarding pointer. AliasSet *Forward; // Forwarding pointer.
AliasSet *Next, *Prev; // Doubly linked list of AliasSets. AliasSet *Next, *Prev; // Doubly linked list of AliasSets.
// All calls & invokes in this alias set. // All instructions without a specific address in this alias set.
std::vector<AssertingVH<Instruction> > CallSites; std::vector<AssertingVH<Instruction> > UnknownInsts;
// RefCount - Number of nodes pointing to this AliasSet plus the number of // RefCount - Number of nodes pointing to this AliasSet plus the number of
// AliasSets forwarding to it. // AliasSets forwarding to it.
@ -147,9 +147,9 @@ class AliasSet : public ilist_node<AliasSet> {
removeFromTracker(AST); removeFromTracker(AST);
} }
CallSite getCallSite(unsigned i) const { Instruction *getUnknownInst(unsigned i) const {
assert(i < CallSites.size()); assert(i < UnknownInsts.size());
return CallSite(CallSites[i]); return UnknownInsts[i];
} }
public: public:
@ -253,12 +253,12 @@ class AliasSet : public ilist_node<AliasSet> {
void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size,
const MDNode *TBAAInfo, const MDNode *TBAAInfo,
bool KnownMustAlias = false); bool KnownMustAlias = false);
void addCallSite(CallSite CS, AliasAnalysis &AA); void addUnknownInst(Instruction *I, AliasAnalysis &AA);
void removeCallSite(CallSite CS) { void removeUnknownInst(Instruction *I) {
for (size_t i = 0, e = CallSites.size(); i != e; ++i) for (size_t i = 0, e = UnknownInsts.size(); i != e; ++i)
if (CallSites[i] == CS.getInstruction()) { if (UnknownInsts[i] == I) {
CallSites[i] = CallSites.back(); UnknownInsts[i] = UnknownInsts.back();
CallSites.pop_back(); UnknownInsts.pop_back();
--i; --e; // Revisit the moved entry. --i; --e; // Revisit the moved entry.
} }
} }
@ -269,7 +269,7 @@ class AliasSet : public ilist_node<AliasSet> {
/// ///
bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo,
AliasAnalysis &AA) const; AliasAnalysis &AA) const;
bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const;
}; };
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) { inline raw_ostream& operator<<(raw_ostream &OS, const AliasSet &AS) {
@ -326,12 +326,10 @@ class AliasSetTracker {
bool add(LoadInst *LI); bool add(LoadInst *LI);
bool add(StoreInst *SI); bool add(StoreInst *SI);
bool add(VAArgInst *VAAI); bool add(VAArgInst *VAAI);
bool add(CallSite CS); // Call/Invoke instructions
bool add(CallInst *CI) { return add(CallSite(CI)); }
bool add(InvokeInst *II) { return add(CallSite(II)); }
bool add(Instruction *I); // Dispatch to one of the other add methods... bool add(Instruction *I); // Dispatch to one of the other add methods...
void add(BasicBlock &BB); // Add all instructions in basic block void add(BasicBlock &BB); // Add all instructions in basic block
void add(const AliasSetTracker &AST); // Add alias relations from another AST void add(const AliasSetTracker &AST); // Add alias relations from another AST
bool addUnknown(Instruction *I);
/// remove methods - These methods are used to remove all entries that might /// remove methods - These methods are used to remove all entries that might
/// be aliased by the specified instruction. These methods return true if any /// be aliased by the specified instruction. These methods return true if any
@ -341,11 +339,9 @@ class AliasSetTracker {
bool remove(LoadInst *LI); bool remove(LoadInst *LI);
bool remove(StoreInst *SI); bool remove(StoreInst *SI);
bool remove(VAArgInst *VAAI); bool remove(VAArgInst *VAAI);
bool remove(CallSite CS);
bool remove(CallInst *CI) { return remove(CallSite(CI)); }
bool remove(InvokeInst *II) { return remove(CallSite(II)); }
bool remove(Instruction *I); bool remove(Instruction *I);
void remove(AliasSet &AS); void remove(AliasSet &AS);
bool removeUnknown(Instruction *I);
void clear(); void clear();
@ -429,7 +425,7 @@ class AliasSetTracker {
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
const MDNode *TBAAInfo); const MDNode *TBAAInfo);
AliasSet *findAliasSetForCallSite(CallSite CS); AliasSet *findAliasSetForUnknownInst(Instruction *Inst);
}; };
inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) { inline raw_ostream& operator<<(raw_ostream &OS, const AliasSetTracker &AST) {

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/PostOrderIterator.h"
#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h" #include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
@ -29,8 +30,8 @@
namespace llvm { namespace llvm {
class BlockFrequency; class BlockFrequencyInfo;
class MachineBlockFrequency; class MachineBlockFrequencyInfo;
/// BlockFrequencyImpl implements block frequency algorithm for IR and /// BlockFrequencyImpl implements block frequency algorithm for IR and
/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) /// Machine Instructions. Algorithm starts with value 1024 (START_FREQ)
@ -40,7 +41,7 @@ class MachineBlockFrequency;
template<class BlockT, class FunctionT, class BlockProbInfoT> template<class BlockT, class FunctionT, class BlockProbInfoT>
class BlockFrequencyImpl { class BlockFrequencyImpl {
DenseMap<BlockT *, uint32_t> Freqs; DenseMap<BlockT *, BlockFrequency> Freqs;
BlockProbInfoT *BPI; BlockProbInfoT *BPI;
@ -48,7 +49,7 @@ class BlockFrequencyImpl {
typedef GraphTraits< Inverse<BlockT *> > GT; typedef GraphTraits< Inverse<BlockT *> > GT;
static const uint32_t START_FREQ = 1024; const uint32_t EntryFreq;
std::string getBlockName(BasicBlock *BB) const { std::string getBlockName(BasicBlock *BB) const {
return BB->getNameStr(); return BB->getNameStr();
@ -64,26 +65,21 @@ class BlockFrequencyImpl {
return ss.str(); return ss.str();
} }
void setBlockFreq(BlockT *BB, uint32_t Freq) { void setBlockFreq(BlockT *BB, BlockFrequency Freq) {
Freqs[BB] = Freq; Freqs[BB] = Freq;
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n"); DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") = " << Freq << "\n");
} }
/// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst /// getEdgeFreq - Return edge frequency based on SRC frequency and Src -> Dst
/// edge probability. /// edge probability.
uint32_t getEdgeFreq(BlockT *Src, BlockT *Dst) const { BlockFrequency getEdgeFreq(BlockT *Src, BlockT *Dst) const {
BranchProbability Prob = BPI->getEdgeProbability(Src, Dst); BranchProbability Prob = BPI->getEdgeProbability(Src, Dst);
uint64_t N = Prob.getNumerator(); return getBlockFreq(Src) * Prob;
uint64_t D = Prob.getDenominator();
uint64_t Res = (N * getBlockFreq(Src)) / D;
assert(Res <= UINT32_MAX);
return (uint32_t) Res;
} }
/// incBlockFreq - Increase BB block frequency by FREQ. /// incBlockFreq - Increase BB block frequency by FREQ.
/// ///
void incBlockFreq(BlockT *BB, uint32_t Freq) { void incBlockFreq(BlockT *BB, BlockFrequency Freq) {
Freqs[BB] += Freq; Freqs[BB] += Freq;
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") += " << Freq
<< " --> " << Freqs[BB] << "\n"); << " --> " << Freqs[BB] << "\n");
@ -95,13 +91,13 @@ class BlockFrequencyImpl {
uint64_t N = Prob.getNumerator(); uint64_t N = Prob.getNumerator();
assert(N && "Illegal division by zero!"); assert(N && "Illegal division by zero!");
uint64_t D = Prob.getDenominator(); uint64_t D = Prob.getDenominator();
uint64_t Freq = (Freqs[BB] * D) / N; uint64_t Freq = (Freqs[BB].getFrequency() * D) / N;
// Should we assert it? // Should we assert it?
if (Freq > UINT32_MAX) if (Freq > UINT32_MAX)
Freq = UINT32_MAX; Freq = UINT32_MAX;
Freqs[BB] = (uint32_t) Freq; Freqs[BB] = BlockFrequency(Freq);
DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob
<< ") --> " << Freqs[BB] << "\n"); << ") --> " << Freqs[BB] << "\n");
} }
@ -136,15 +132,6 @@ class BlockFrequencyImpl {
} }
/// Return a probability of getting to the DST block through SRC->DST edge.
///
BranchProbability getBackEdgeProbability(BlockT *Src, BlockT *Dst) const {
uint32_t N = getEdgeFreq(Src, Dst);
uint32_t D = getBlockFreq(Dst);
return BranchProbability(N, D);
}
/// isReachable - Returns if BB block is reachable from the entry. /// isReachable - Returns if BB block is reachable from the entry.
/// ///
bool isReachable(BlockT *BB) { bool isReachable(BlockT *BB) {
@ -160,7 +147,7 @@ class BlockFrequencyImpl {
unsigned a = RPO[Src]; unsigned a = RPO[Src];
unsigned b = RPO[Dst]; unsigned b = RPO[Dst];
return a > b; return a >= b;
} }
/// getSingleBlockPred - return single BB block predecessor or NULL if /// getSingleBlockPred - return single BB block predecessor or NULL if
@ -189,7 +176,7 @@ class BlockFrequencyImpl {
setBlockFreq(BB, 0); setBlockFreq(BB, 0);
if (BB == LoopHead) { if (BB == LoopHead) {
setBlockFreq(BB, START_FREQ); setBlockFreq(BB, EntryFreq);
return; return;
} }
@ -224,10 +211,10 @@ class BlockFrequencyImpl {
if (!isLoopHead) if (!isLoopHead)
return; return;
assert(START_FREQ >= CycleProb[BB]); assert(EntryFreq >= CycleProb[BB]);
uint32_t CProb = CycleProb[BB]; uint32_t CProb = CycleProb[BB];
uint32_t Numerator = START_FREQ - CProb ? START_FREQ - CProb : 1; uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1;
divBlockFreq(BB, BranchProbability(Numerator, START_FREQ)); divBlockFreq(BB, BranchProbability(Numerator, EntryFreq));
} }
/// doLoop - Propagate block frequency down throught the loop. /// doLoop - Propagate block frequency down throught the loop.
@ -237,11 +224,13 @@ class BlockFrequencyImpl {
SmallPtrSet<BlockT *, 8> BlocksInLoop; SmallPtrSet<BlockT *, 8> BlocksInLoop;
for (rpot_iterator I = rpot_at(Head), E = rpot_end(); I != E; ++I) { for (rpot_iterator I = rpot_at(Head), E = rpot_at(Tail); ; ++I) {
BlockT *BB = *I; BlockT *BB = *I;
doBlock(BB, Head, BlocksInLoop); doBlock(BB, Head, BlocksInLoop);
BlocksInLoop.insert(BB); BlocksInLoop.insert(BB);
if (I == E)
break;
} }
// Compute loop's cyclic probability using backedges probabilities. // Compute loop's cyclic probability using backedges probabilities.
@ -252,19 +241,23 @@ class BlockFrequencyImpl {
BlockT *Pred = *PI; BlockT *Pred = *PI;
assert(Pred); assert(Pred);
if (isReachable(Pred) && isBackedge(Pred, Head)) { if (isReachable(Pred) && isBackedge(Pred, Head)) {
BranchProbability Prob = getBackEdgeProbability(Pred, Head); uint64_t N = getEdgeFreq(Pred, Head).getFrequency();
uint64_t N = Prob.getNumerator(); uint64_t D = getBlockFreq(Head).getFrequency();
uint64_t D = Prob.getDenominator(); assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!");
uint64_t Res = (N * START_FREQ) / D; uint64_t Res = (N * EntryFreq) / D;
assert(Res <= UINT32_MAX); assert(Res <= UINT32_MAX);
CycleProb[Head] += (uint32_t) Res; CycleProb[Head] += (uint32_t) Res;
DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res
<< " --> " << CycleProb[Head] << "\n");
} }
} }
} }
friend class BlockFrequency; friend class BlockFrequencyInfo;
friend class MachineBlockFrequency; friend class MachineBlockFrequencyInfo;
BlockFrequencyImpl() : EntryFreq(BlockFrequency::getEntryFrequency()) { }
void doFunction(FunctionT *fn, BlockProbInfoT *bpi) { void doFunction(FunctionT *fn, BlockProbInfoT *bpi) {
Fn = fn; Fn = fn;
@ -314,13 +307,12 @@ class BlockFrequencyImpl {
} }
public: public:
/// getBlockFreq - Return block frequency. Never return 0, value must be /// getBlockFreq - Return block frequency. Return 0 if we don't have it.
/// positive. BlockFrequency getBlockFreq(BlockT *BB) const {
uint32_t getBlockFreq(BlockT *BB) const { typename DenseMap<BlockT *, BlockFrequency>::const_iterator I = Freqs.find(BB);
typename DenseMap<BlockT *, uint32_t>::const_iterator I = Freqs.find(BB);
if (I != Freqs.end()) if (I != Freqs.end())
return I->second ? I->second : 1; return I->second;
return 1; return 0;
} }
void print(raw_ostream &OS) const { void print(raw_ostream &OS) const {

View File

@ -1,4 +1,4 @@
//========-------- BlockFrequency.h - Block Frequency Analysis -------========// //========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -11,10 +11,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCY_H #ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
#define LLVM_ANALYSIS_BLOCKFREQUENCY_H #define LLVM_ANALYSIS_BLOCKFREQUENCYINFO_H
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits> #include <climits>
namespace llvm { namespace llvm {
@ -23,29 +24,30 @@ class BranchProbabilityInfo;
template<class BlockT, class FunctionT, class BranchProbInfoT> template<class BlockT, class FunctionT, class BranchProbInfoT>
class BlockFrequencyImpl; class BlockFrequencyImpl;
/// BlockFrequency pass uses BlockFrequencyImpl implementation to estimate /// BlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
/// IR basic block frequencies. /// IR basic block frequencies.
class BlockFrequency : public FunctionPass { class BlockFrequencyInfo : public FunctionPass {
BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI; BlockFrequencyImpl<BasicBlock, Function, BranchProbabilityInfo> *BFI;
public: public:
static char ID; static char ID;
BlockFrequency(); BlockFrequencyInfo();
~BlockFrequency(); ~BlockFrequencyInfo();
void getAnalysisUsage(AnalysisUsage &AU) const; void getAnalysisUsage(AnalysisUsage &AU) const;
bool runOnFunction(Function &F); bool runOnFunction(Function &F);
void print(raw_ostream &O, const Module *M) const;
/// getblockFreq - Return block frequency. Never return 0, value must be /// getblockFreq - Return block frequency. Return 0 if we don't have the
/// positive. Please note that initial frequency is equal to 1024. It means /// information. Please note that initial frequency is equal to 1024. It means
/// that we should not rely on the value itself, but only on the comparison to /// that we should not rely on the value itself, but only on the comparison to
/// the other block frequencies. We do this to avoid using of the floating /// the other block frequencies. We do this to avoid using of floating points.
/// points. ///
uint32_t getBlockFreq(BasicBlock *BB); BlockFrequency getBlockFreq(BasicBlock *BB) const;
}; };
} }

View File

@ -33,12 +33,12 @@ class BranchProbabilityInfo : public FunctionPass {
// weight to just "inherit" the non-zero weight of an adjacent successor. // weight to just "inherit" the non-zero weight of an adjacent successor.
static const uint32_t DEFAULT_WEIGHT = 16; static const uint32_t DEFAULT_WEIGHT = 16;
typedef std::pair<BasicBlock *, BasicBlock *> Edge; typedef std::pair<const BasicBlock *, const BasicBlock *> Edge;
DenseMap<Edge, uint32_t> Weights; DenseMap<Edge, uint32_t> Weights;
// Get sum of the block successors' weights. // Get sum of the block successors' weights.
uint32_t getSumForBlock(BasicBlock *BB) const; uint32_t getSumForBlock(const BasicBlock *BB) const;
public: public:
static char ID; static char ID;
@ -53,13 +53,14 @@ class BranchProbabilityInfo : public FunctionPass {
// Returned value is between 1 and UINT32_MAX. Look at // Returned value is between 1 and UINT32_MAX. Look at
// BranchProbabilityInfo.cpp for details. // BranchProbabilityInfo.cpp for details.
uint32_t getEdgeWeight(BasicBlock *Src, BasicBlock *Dst) const; uint32_t getEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst) const;
// Look at BranchProbabilityInfo.cpp for details. Use it with caution! // Look at BranchProbabilityInfo.cpp for details. Use it with caution!
void setEdgeWeight(BasicBlock *Src, BasicBlock *Dst, uint32_t Weight); void setEdgeWeight(const BasicBlock *Src, const BasicBlock *Dst,
uint32_t Weight);
// A 'Hot' edge is an edge which probability is >= 80%. // A 'Hot' edge is an edge which probability is >= 80%.
bool isEdgeHot(BasicBlock *Src, BasicBlock *Dst) const; bool isEdgeHot(const BasicBlock *Src, const BasicBlock *Dst) const;
// Return a hot successor for the block BB or null if there isn't one. // Return a hot successor for the block BB or null if there isn't one.
BasicBlock *getHotSucc(BasicBlock *BB) const; BasicBlock *getHotSucc(BasicBlock *BB) const;
@ -67,7 +68,8 @@ class BranchProbabilityInfo : public FunctionPass {
// Return a probability as a fraction between 0 (0% probability) and // Return a probability as a fraction between 0 (0% probability) and
// 1 (100% probability), however the value is never equal to 0, and can be 1 // 1 (100% probability), however the value is never equal to 0, and can be 1
// only iff SRC block has only one successor. // only iff SRC block has only one successor.
BranchProbability getEdgeProbability(BasicBlock *Src, BasicBlock *Dst) const; BranchProbability getEdgeProbability(const BasicBlock *Src,
const BasicBlock *Dst) const;
// Print value between 0 (0% probability) and 1 (100% probability), // Print value between 0 (0% probability) and 1 (100% probability),
// however the value is never equal to 0, and can be 1 only iff SRC block // however the value is never equal to 0, and can be 1 only iff SRC block

View File

@ -18,6 +18,9 @@
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
namespace llvm { namespace llvm {
class TargetData;
// CodeMetrics - Calculate size and a few similar metrics for a set of // CodeMetrics - Calculate size and a few similar metrics for a set of
// basic blocks. // basic blocks.
struct CodeMetrics { struct CodeMetrics {
@ -46,7 +49,7 @@ namespace llvm {
/// NumCalls - Keep track of the number of calls to 'big' functions. /// NumCalls - Keep track of the number of calls to 'big' functions.
unsigned NumCalls; unsigned NumCalls;
/// NumInlineCandidates - Keep track of the number of calls to internal /// NumInlineCandidates - Keep track of the number of calls to internal
/// functions with only a single caller. These are likely targets for /// functions with only a single caller. These are likely targets for
/// future inlining, likely exposed by interleaved devirtualization. /// future inlining, likely exposed by interleaved devirtualization.
@ -61,24 +64,24 @@ namespace llvm {
unsigned NumRets; unsigned NumRets;
CodeMetrics() : callsSetJmp(false), isRecursive(false), CodeMetrics() : callsSetJmp(false), isRecursive(false),
containsIndirectBr(false), usesDynamicAlloca(false), containsIndirectBr(false), usesDynamicAlloca(false),
NumInsts(0), NumBlocks(0), NumCalls(0), NumInsts(0), NumBlocks(0), NumCalls(0),
NumInlineCandidates(0), NumVectorInsts(0), NumInlineCandidates(0), NumVectorInsts(0),
NumRets(0) {} NumRets(0) {}
/// analyzeBasicBlock - Add information about the specified basic block /// analyzeBasicBlock - Add information about the specified basic block
/// to the current structure. /// to the current structure.
void analyzeBasicBlock(const BasicBlock *BB); void analyzeBasicBlock(const BasicBlock *BB, const TargetData *TD = 0);
/// analyzeFunction - Add information about the specified function /// analyzeFunction - Add information about the specified function
/// to the current structure. /// to the current structure.
void analyzeFunction(Function *F); void analyzeFunction(Function *F, const TargetData *TD = 0);
/// CountCodeReductionForConstant - Figure out an approximation for how /// CountCodeReductionForConstant - Figure out an approximation for how
/// many instructions will be constant folded if the specified value is /// many instructions will be constant folded if the specified value is
/// constant. /// constant.
unsigned CountCodeReductionForConstant(Value *V); unsigned CountCodeReductionForConstant(Value *V);
/// CountBonusForConstant - Figure out an approximation for how much /// CountBonusForConstant - Figure out an approximation for how much
/// per-call performance boost we can expect if the specified value is /// per-call performance boost we can expect if the specified value is
/// constant. /// constant.

View File

@ -27,6 +27,8 @@ namespace llvm {
class TargetData; class TargetData;
class Function; class Function;
class Type; class Type;
template<typename T>
class ArrayRef;
/// ConstantFoldInstruction - Try to constant fold the specified instruction. /// ConstantFoldInstruction - Try to constant fold the specified instruction.
/// If successful, the constant result is returned, if not, null is returned. /// If successful, the constant result is returned, if not, null is returned.
@ -47,8 +49,8 @@ Constant *ConstantFoldConstantExpression(const ConstantExpr *CE,
/// fold instructions like loads and stores, which have no constant expression /// fold instructions like loads and stores, which have no constant expression
/// form. /// form.
/// ///
Constant *ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy, Constant *ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
Constant *const *Ops, unsigned NumOps, ArrayRef<Constant *> Ops,
const TargetData *TD = 0); const TargetData *TD = 0);
/// ConstantFoldCompareInstOperands - Attempt to constant fold a compare /// ConstantFoldCompareInstOperands - Attempt to constant fold a compare
@ -59,6 +61,12 @@ Constant *ConstantFoldCompareInstOperands(unsigned Predicate,
Constant *LHS, Constant *RHS, Constant *LHS, Constant *RHS,
const TargetData *TD = 0); const TargetData *TD = 0);
/// ConstantFoldInsertValueInstruction - Attempt to constant fold an insertvalue
/// instruction with the specified operands and indices. The constant result is
/// returned if successful; if not, null is returned.
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs);
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable, /// produce if it is constant and determinable. If this is not determinable,
/// return null. /// return null.
@ -76,7 +84,7 @@ bool canConstantFoldCallTo(const Function *F);
/// ConstantFoldCall - Attempt to constant fold a call to the specified function /// ConstantFoldCall - Attempt to constant fold a call to the specified function
/// with the specified arguments, returning null if unsuccessful. /// with the specified arguments, returning null if unsuccessful.
Constant * Constant *
ConstantFoldCall(Function *F, Constant *const *Operands, unsigned NumOperands); ConstantFoldCall(Function *F, ArrayRef<Constant *> Operands);
} }
#endif #endif

View File

@ -37,6 +37,7 @@ namespace llvm {
class DINameSpace; class DINameSpace;
class DIVariable; class DIVariable;
class DISubrange; class DISubrange;
class DILexicalBlockFile;
class DILexicalBlock; class DILexicalBlock;
class DISubprogram; class DISubprogram;
class DITemplateTypeParameter; class DITemplateTypeParameter;
@ -48,9 +49,19 @@ namespace llvm {
LLVMContext & VMContext; LLVMContext & VMContext;
MDNode *TheCU; MDNode *TheCU;
MDNode *TempEnumTypes;
MDNode *TempRetainTypes;
MDNode *TempSubprograms;
MDNode *TempGVs;
Function *DeclareFn; // llvm.dbg.declare Function *DeclareFn; // llvm.dbg.declare
Function *ValueFn; // llvm.dbg.value Function *ValueFn; // llvm.dbg.value
SmallVector<Value *, 4> AllEnumTypes;
SmallVector<Value *, 4> AllRetainTypes;
SmallVector<Value *, 4> AllSubprograms;
SmallVector<Value *, 4> AllGVs;
DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT DIBuilder(const DIBuilder &); // DO NOT IMPLEMENT
void operator=(const DIBuilder &); // DO NOT IMPLEMENT void operator=(const DIBuilder &); // DO NOT IMPLEMENT
@ -59,6 +70,9 @@ namespace llvm {
const MDNode *getCU() { return TheCU; } const MDNode *getCU() { return TheCU; }
enum ComplexAddrKind { OpPlus=1, OpDeref }; enum ComplexAddrKind { OpPlus=1, OpDeref };
/// finalize - Construct any deferred debug info descriptors.
void finalize();
/// createCompileUnit - A CompileUnit provides an anchor for all debugging /// createCompileUnit - A CompileUnit provides an anchor for all debugging
/// information generated during this instance of compilation. /// information generated during this instance of compilation.
/// @param Lang Source programming language, eg. dwarf::DW_LANG_C99 /// @param Lang Source programming language, eg. dwarf::DW_LANG_C99
@ -84,6 +98,9 @@ namespace llvm {
/// createEnumerator - Create a single enumerator value. /// createEnumerator - Create a single enumerator value.
DIEnumerator createEnumerator(StringRef Name, uint64_t Val); DIEnumerator createEnumerator(StringRef Name, uint64_t Val);
/// createNullPtrType - Create C++0x nullptr type.
DIType createNullPtrType(StringRef Name);
/// createBasicType - Create debugging information entry for a basic /// createBasicType - Create debugging information entry for a basic
/// type. /// type.
/// @param Name Type name. /// @param Name Type name.
@ -447,6 +464,14 @@ namespace llvm {
DIFile File, unsigned LineNo); DIFile File, unsigned LineNo);
/// createLexicalBlockFile - This creates a descriptor for a lexical
/// block with a new file attached. This merely extends the existing
/// lexical block as it crosses a file.
/// @param Scope Lexical block.
/// @param File Source file.
DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope,
DIFile File);
/// createLexicalBlock - This creates a descriptor for a lexical block /// createLexicalBlock - This creates a descriptor for a lexical block
/// with the specified parent context. /// with the specified parent context.
/// @param Scope Parent lexical scope. /// @param Scope Parent lexical scope.

View File

@ -40,6 +40,7 @@ namespace llvm {
class DIFile; class DIFile;
class DISubprogram; class DISubprogram;
class DILexicalBlock; class DILexicalBlock;
class DILexicalBlockFile;
class DIVariable; class DIVariable;
class DIType; class DIType;
@ -84,6 +85,7 @@ namespace llvm {
explicit DIDescriptor(const MDNode *N) : DbgNode(N) {} explicit DIDescriptor(const MDNode *N) : DbgNode(N) {}
explicit DIDescriptor(const DIFile F); explicit DIDescriptor(const DIFile F);
explicit DIDescriptor(const DISubprogram F); explicit DIDescriptor(const DISubprogram F);
explicit DIDescriptor(const DILexicalBlockFile F);
explicit DIDescriptor(const DILexicalBlock F); explicit DIDescriptor(const DILexicalBlock F);
explicit DIDescriptor(const DIVariable F); explicit DIDescriptor(const DIVariable F);
explicit DIDescriptor(const DIType F); explicit DIDescriptor(const DIType F);
@ -117,6 +119,7 @@ namespace llvm {
bool isFile() const; bool isFile() const;
bool isCompileUnit() const; bool isCompileUnit() const;
bool isNameSpace() const; bool isNameSpace() const;
bool isLexicalBlockFile() const;
bool isLexicalBlock() const; bool isLexicalBlock() const;
bool isSubrange() const; bool isSubrange() const;
bool isEnumerator() const; bool isEnumerator() const;
@ -182,6 +185,11 @@ namespace llvm {
StringRef getFlags() const { return getStringField(8); } StringRef getFlags() const { return getStringField(8); }
unsigned getRunTimeVersion() const { return getUnsignedField(9); } unsigned getRunTimeVersion() const { return getUnsignedField(9); }
DIArray getEnumTypes() const;
DIArray getRetainedTypes() const;
DIArray getSubprograms() const;
DIArray getGlobalVariables() const;
/// Verify - Verify that a compile unit is well formed. /// Verify - Verify that a compile unit is well formed.
bool Verify() const; bool Verify() const;
@ -201,7 +209,10 @@ namespace llvm {
} }
StringRef getFilename() const { return getStringField(1); } StringRef getFilename() const { return getStringField(1); }
StringRef getDirectory() const { return getStringField(2); } StringRef getDirectory() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{ return getFieldAs<DICompileUnit>(3); } DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid CompileUnit!");
return getFieldAs<DICompileUnit>(3);
}
}; };
/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). /// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}').
@ -237,6 +248,7 @@ namespace llvm {
DIScope getContext() const { return getFieldAs<DIScope>(1); } DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); } StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{ DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7) if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3); return getFieldAs<DICompileUnit>(3);
@ -291,6 +303,9 @@ namespace llvm {
return getFieldAs<DIFile>(3).getFilename(); return getFieldAs<DIFile>(3).getFilename();
} }
/// isUnsignedDIType - Return true if type encoding is unsigned.
bool isUnsignedDIType();
/// replaceAllUsesWith - Replace all uses of debug info referenced by /// replaceAllUsesWith - Replace all uses of debug info referenced by
/// this descriptor. /// this descriptor.
void replaceAllUsesWith(DIDescriptor &D); void replaceAllUsesWith(DIDescriptor &D);
@ -447,6 +462,7 @@ namespace llvm {
StringRef getDisplayName() const { return getStringField(4); } StringRef getDisplayName() const { return getStringField(4); }
StringRef getLinkageName() const { return getStringField(5); } StringRef getLinkageName() const { return getStringField(5); }
DICompileUnit getCompileUnit() const{ DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7) if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(6); return getFieldAs<DICompileUnit>(6);
@ -545,6 +561,8 @@ namespace llvm {
DISubprogram getFunctionDeclaration() const { DISubprogram getFunctionDeclaration() const {
return getFieldAs<DISubprogram>(18); return getFieldAs<DISubprogram>(18);
} }
MDNode *getVariablesNodes() const;
DIArray getVariables() const;
}; };
/// DIGlobalVariable - This is a wrapper for a global variable. /// DIGlobalVariable - This is a wrapper for a global variable.
@ -557,12 +575,24 @@ namespace llvm {
StringRef getDisplayName() const { return getStringField(4); } StringRef getDisplayName() const { return getStringField(4); }
StringRef getLinkageName() const { return getStringField(5); } StringRef getLinkageName() const { return getStringField(5); }
DICompileUnit getCompileUnit() const{ DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7) if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(6); return getFieldAs<DICompileUnit>(6);
DIFile F = getFieldAs<DIFile>(6); DIFile F = getFieldAs<DIFile>(6);
return F.getCompileUnit(); return F.getCompileUnit();
} }
StringRef getFilename() const {
if (getVersion() <= llvm::LLVMDebugVersion10)
return getContext().getFilename();
return getFieldAs<DIFile>(6).getFilename();
}
StringRef getDirectory() const {
if (getVersion() <= llvm::LLVMDebugVersion10)
return getContext().getDirectory();
return getFieldAs<DIFile>(6).getDirectory();
}
unsigned getLineNumber() const { return getUnsignedField(7); } unsigned getLineNumber() const { return getUnsignedField(7); }
DIType getType() const { return getFieldAs<DIType>(8); } DIType getType() const { return getFieldAs<DIType>(8); }
@ -592,6 +622,7 @@ namespace llvm {
DIScope getContext() const { return getFieldAs<DIScope>(1); } DIScope getContext() const { return getFieldAs<DIScope>(1); }
StringRef getName() const { return getStringField(2); } StringRef getName() const { return getStringField(2); }
DICompileUnit getCompileUnit() const{ DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7) if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3); return getFieldAs<DICompileUnit>(3);
@ -614,6 +645,8 @@ namespace llvm {
return (getUnsignedField(6) & FlagArtificial) != 0; return (getUnsignedField(6) & FlagArtificial) != 0;
} }
/// getInlinedAt - If this variable is inlined then return inline location.
MDNode *getInlinedAt() const;
/// Verify - Verify that a variable descriptor is well formed. /// Verify - Verify that a variable descriptor is well formed.
bool Verify() const; bool Verify() const;
@ -628,7 +661,9 @@ namespace llvm {
uint64_t getAddrElement(unsigned Idx) const { uint64_t getAddrElement(unsigned Idx) const {
if (getVersion() <= llvm::LLVMDebugVersion8) if (getVersion() <= llvm::LLVMDebugVersion8)
return getUInt64Field(Idx+6); return getUInt64Field(Idx+6);
return getUInt64Field(Idx+7); if (getVersion() == llvm::LLVMDebugVersion9)
return getUInt64Field(Idx+7);
return getUInt64Field(Idx+8);
} }
/// isBlockByrefVariable - Return true if the variable was declared as /// isBlockByrefVariable - Return true if the variable was declared as
@ -644,6 +679,8 @@ namespace llvm {
/// print - print variable. /// print - print variable.
void print(raw_ostream &OS) const; void print(raw_ostream &OS) const;
void printExtendedName(raw_ostream &OS) const;
/// dump - print variable to dbgs() with a newline. /// dump - print variable to dbgs() with a newline.
void dump() const; void dump() const;
}; };
@ -665,6 +702,26 @@ namespace llvm {
} }
}; };
/// DILexicalBlockFile - This is a wrapper for a lexical block with
/// a filename change.
class DILexicalBlockFile : public DIScope {
public:
explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {}
DIScope getContext() const { return getScope().getContext(); }
unsigned getLineNumber() const { return getScope().getLineNumber(); }
unsigned getColumnNumber() const { return getScope().getColumnNumber(); }
StringRef getDirectory() const {
StringRef dir = getFieldAs<DIFile>(2).getDirectory();
return !dir.empty() ? dir : getContext().getDirectory();
}
StringRef getFilename() const {
StringRef filename = getFieldAs<DIFile>(2).getFilename();
assert(!filename.empty() && "Why'd you create this then?");
return filename;
}
DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(1); }
};
/// DINameSpace - A wrapper for a C++ style name space. /// DINameSpace - A wrapper for a C++ style name space.
class DINameSpace : public DIScope { class DINameSpace : public DIScope {
public: public:
@ -678,6 +735,7 @@ namespace llvm {
return getFieldAs<DIFile>(3).getFilename(); return getFieldAs<DIFile>(3).getFilename();
} }
DICompileUnit getCompileUnit() const{ DICompileUnit getCompileUnit() const{
assert (getVersion() <= LLVMDebugVersion10 && "Invalid getCompileUnit!");
if (getVersion() == llvm::LLVMDebugVersion7) if (getVersion() == llvm::LLVMDebugVersion7)
return getFieldAs<DICompileUnit>(3); return getFieldAs<DICompileUnit>(3);
@ -708,13 +766,27 @@ namespace llvm {
/// getDICompositeType - Find underlying composite type. /// getDICompositeType - Find underlying composite type.
DICompositeType getDICompositeType(DIType T); DICompositeType getDICompositeType(DIType T);
/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
bool isSubprogramContext(const MDNode *Context);
/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable /// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
/// to hold function specific information. /// to hold function specific information.
NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, StringRef Name); NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP);
/// getFnSpecificMDNode - Return a NameMDNode, if available, that is /// getFnSpecificMDNode - Return a NameMDNode, if available, that is
/// suitable to hold function specific information. /// suitable to hold function specific information.
NamedMDNode *getFnSpecificMDNode(const Module &M, StringRef Name); NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP);
/// createInlinedVariable - Create a new inlined variable based on current
/// variable.
/// @param DV Current Variable.
/// @param InlinedScope Location at current variable is inlined.
DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
LLVMContext &VMContext);
/// cleanseInlinedVariable - Remove inlined scope from the variable.
DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext);
class DebugInfoFinder { class DebugInfoFinder {
public: public:

View File

@ -23,7 +23,7 @@ class Type;
class Value; class Value;
class FindUsedTypes : public ModulePass { class FindUsedTypes : public ModulePass {
SetVector<const Type *> UsedTypes; SetVector<Type *> UsedTypes;
public: public:
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
FindUsedTypes() : ModulePass(ID) { FindUsedTypes() : ModulePass(ID) {
@ -33,7 +33,7 @@ class FindUsedTypes : public ModulePass {
/// getTypes - After the pass has been run, return the set containing all of /// getTypes - After the pass has been run, return the set containing all of
/// the types used in the module. /// the types used in the module.
/// ///
const SetVector<const Type *> &getTypes() const { return UsedTypes; } const SetVector<Type *> &getTypes() const { return UsedTypes; }
/// Print the types found in the module. If the optional Module parameter is /// Print the types found in the module. If the optional Module parameter is
/// passed in, then the types are printed symbolically if possible, using the /// passed in, then the types are printed symbolically if possible, using the
@ -45,7 +45,7 @@ class FindUsedTypes : public ModulePass {
/// IncorporateType - Incorporate one type and all of its subtypes into the /// IncorporateType - Incorporate one type and all of its subtypes into the
/// collection of used types. /// collection of used types.
/// ///
void IncorporateType(const Type *Ty); void IncorporateType(Type *Ty);
/// IncorporateValue - Incorporate all of the types used by this value. /// IncorporateValue - Incorporate all of the types used by this value.
/// ///

View File

@ -140,6 +140,8 @@ class IVUsers : public LoopPass {
static char ID; // Pass ID, replacement for typeid static char ID; // Pass ID, replacement for typeid
IVUsers(); IVUsers();
Loop *getLoop() const { return L; }
/// AddUsersIfInteresting - Inspect the specified Instruction. If it is a /// AddUsersIfInteresting - Inspect the specified Instruction. If it is a
/// reducible SCEV, recursively add its users to the IVUsesByStride set and /// reducible SCEV, recursively add its users to the IVUsesByStride set and
/// return true. Otherwise, return false. /// return true. Otherwise, return false.

View File

@ -29,6 +29,7 @@ namespace llvm {
class CallSite; class CallSite;
template<class PtrType, unsigned SmallSize> template<class PtrType, unsigned SmallSize>
class SmallPtrSet; class SmallPtrSet;
class TargetData;
namespace InlineConstants { namespace InlineConstants {
// Various magic constants used to adjust heuristics. // Various magic constants used to adjust heuristics.
@ -113,7 +114,7 @@ namespace llvm {
/// analyzeFunction - Add information about the specified function /// analyzeFunction - Add information about the specified function
/// to the current structure. /// to the current structure.
void analyzeFunction(Function *F); void analyzeFunction(Function *F, const TargetData *TD);
/// NeverInline - Returns true if the function should never be /// NeverInline - Returns true if the function should never be
/// inlined into any caller. /// inlined into any caller.
@ -124,11 +125,17 @@ namespace llvm {
// the ValueMap will update itself when this happens. // the ValueMap will update itself when this happens.
ValueMap<const Function *, FunctionInfo> CachedFunctionInfo; ValueMap<const Function *, FunctionInfo> CachedFunctionInfo;
// TargetData if available, or null.
const TargetData *TD;
int CountBonusForConstant(Value *V, Constant *C = NULL); int CountBonusForConstant(Value *V, Constant *C = NULL);
int ConstantFunctionBonus(CallSite CS, Constant *C); int ConstantFunctionBonus(CallSite CS, Constant *C);
int getInlineSize(CallSite CS, Function *Callee); int getInlineSize(CallSite CS, Function *Callee);
int getInlineBonuses(CallSite CS, Function *Callee); int getInlineBonuses(CallSite CS, Function *Callee);
public: public:
InlineCostAnalyzer(): TD(0) {}
void setTargetData(const TargetData *TData) { TD = TData; }
/// getInlineCost - The heuristic used to determine if we should inline the /// getInlineCost - The heuristic used to determine if we should inline the
/// function call or not. /// function call or not.

View File

@ -24,6 +24,8 @@ namespace llvm {
class Instruction; class Instruction;
class Value; class Value;
class TargetData; class TargetData;
template<typename T>
class ArrayRef;
/// SimplifyAddInst - Given operands for an Add, see if we can /// SimplifyAddInst - Given operands for an Add, see if we can
/// fold the result. If not, this returns null. /// fold the result. If not, this returns null.
@ -121,9 +123,16 @@ namespace llvm {
/// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can
/// fold the result. If not, this returns null. /// fold the result. If not, this returns null.
Value *SimplifyGEPInst(Value * const *Ops, unsigned NumOps, Value *SimplifyGEPInst(ArrayRef<Value *> Ops,
const TargetData *TD = 0, const DominatorTree *DT = 0); const TargetData *TD = 0, const DominatorTree *DT = 0);
/// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we
/// can fold the result. If not, this returns null.
Value *SimplifyInsertValueInst(Value *Agg, Value *Val,
ArrayRef<unsigned> Idxs,
const TargetData *TD = 0,
const DominatorTree *DT = 0);
//=== Helper functions for higher up the class hierarchy. //=== Helper functions for higher up the class hierarchy.

View File

@ -33,6 +33,7 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -105,7 +106,7 @@ class LoopBase {
if (L == 0) return false; if (L == 0) return false;
return contains(L->getParentLoop()); return contains(L->getParentLoop());
} }
/// contains - Return true if the specified basic block is in this loop. /// contains - Return true if the specified basic block is in this loop.
/// ///
bool contains(const BlockT *BB) const { bool contains(const BlockT *BB) const {
@ -134,6 +135,11 @@ class LoopBase {
block_iterator block_begin() const { return Blocks.begin(); } block_iterator block_begin() const { return Blocks.begin(); }
block_iterator block_end() const { return Blocks.end(); } block_iterator block_end() const { return Blocks.end(); }
/// getNumBlocks - Get the number of blocks in this loop in constant time.
unsigned getNumBlocks() const {
return Blocks.size();
}
/// isLoopExiting - True if terminator in the block can branch to another /// isLoopExiting - True if terminator in the block can branch to another
/// block that is outside of the current loop. /// block that is outside of the current loop.
/// ///
@ -479,12 +485,13 @@ class LoopBase {
} }
/// verifyLoop - Verify loop structure of this loop and all nested loops. /// verifyLoop - Verify loop structure of this loop and all nested loops.
void verifyLoopNest() const { void verifyLoopNest(DenseSet<const LoopT*> *Loops) const {
Loops->insert(static_cast<const LoopT *>(this));
// Verify this loop. // Verify this loop.
verifyLoop(); verifyLoop();
// Verify the subloops. // Verify the subloops.
for (iterator I = begin(), E = end(); I != E; ++I) for (iterator I = begin(), E = end(); I != E; ++I)
(*I)->verifyLoopNest(); (*I)->verifyLoopNest(Loops);
} }
void print(raw_ostream &OS, unsigned Depth = 0) const { void print(raw_ostream &OS, unsigned Depth = 0) const {
@ -527,7 +534,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
bool isLoopInvariant(Value *V) const; bool isLoopInvariant(Value *V) const;
/// hasLoopInvariantOperands - Return true if all the operands of the /// hasLoopInvariantOperands - Return true if all the operands of the
/// specified instruction are loop invariant. /// specified instruction are loop invariant.
bool hasLoopInvariantOperands(Instruction *I) const; bool hasLoopInvariantOperands(Instruction *I) const;
/// makeLoopInvariant - If the given value is an instruction inside of the /// makeLoopInvariant - If the given value is an instruction inside of the
@ -607,7 +614,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
/// has a predecessor that is outside the loop. /// has a predecessor that is outside the loop.
bool hasDedicatedExits() const; bool hasDedicatedExits() const;
/// getUniqueExitBlocks - Return all unique successor blocks of this loop. /// getUniqueExitBlocks - Return all unique successor blocks of this loop.
/// These are the blocks _outside of the current loop_ which are branched to. /// These are the blocks _outside of the current loop_ which are branched to.
/// This assumes that loop exits are in canonical form. /// This assumes that loop exits are in canonical form.
/// ///
@ -618,7 +625,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
BasicBlock *getUniqueExitBlock() const; BasicBlock *getUniqueExitBlock() const;
void dump() const; void dump() const;
private: private:
friend class LoopInfoBase<BasicBlock, Loop>; friend class LoopInfoBase<BasicBlock, Loop>;
explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {} explicit Loop(BasicBlock *BB) : LoopBase<BasicBlock, Loop>(BB) {}
@ -635,13 +642,14 @@ class LoopInfoBase {
DenseMap<BlockT *, LoopT *> BBMap; DenseMap<BlockT *, LoopT *> BBMap;
std::vector<LoopT *> TopLevelLoops; std::vector<LoopT *> TopLevelLoops;
friend class LoopBase<BlockT, LoopT>; friend class LoopBase<BlockT, LoopT>;
friend class LoopInfo;
void operator=(const LoopInfoBase &); // do not implement void operator=(const LoopInfoBase &); // do not implement
LoopInfoBase(const LoopInfo &); // do not implement LoopInfoBase(const LoopInfo &); // do not implement
public: public:
LoopInfoBase() { } LoopInfoBase() { }
~LoopInfoBase() { releaseMemory(); } ~LoopInfoBase() { releaseMemory(); }
void releaseMemory() { void releaseMemory() {
for (typename std::vector<LoopT *>::iterator I = for (typename std::vector<LoopT *>::iterator I =
TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I) TopLevelLoops.begin(), E = TopLevelLoops.end(); I != E; ++I)
@ -650,7 +658,7 @@ class LoopInfoBase {
BBMap.clear(); // Reset internal state of analysis BBMap.clear(); // Reset internal state of analysis
TopLevelLoops.clear(); TopLevelLoops.clear();
} }
/// iterator/begin/end - The interface to the top-level loops in the current /// iterator/begin/end - The interface to the top-level loops in the current
/// function. /// function.
/// ///
@ -658,7 +666,7 @@ class LoopInfoBase {
iterator begin() const { return TopLevelLoops.begin(); } iterator begin() const { return TopLevelLoops.begin(); }
iterator end() const { return TopLevelLoops.end(); } iterator end() const { return TopLevelLoops.end(); }
bool empty() const { return TopLevelLoops.empty(); } bool empty() const { return TopLevelLoops.empty(); }
/// getLoopFor - Return the inner most loop that BB lives in. If a basic /// getLoopFor - Return the inner most loop that BB lives in. If a basic
/// block is in no loop (for example the entry node), null is returned. /// block is in no loop (for example the entry node), null is returned.
/// ///
@ -667,13 +675,13 @@ class LoopInfoBase {
BBMap.find(const_cast<BlockT*>(BB)); BBMap.find(const_cast<BlockT*>(BB));
return I != BBMap.end() ? I->second : 0; return I != BBMap.end() ? I->second : 0;
} }
/// operator[] - same as getLoopFor... /// operator[] - same as getLoopFor...
/// ///
const LoopT *operator[](const BlockT *BB) const { const LoopT *operator[](const BlockT *BB) const {
return getLoopFor(BB); return getLoopFor(BB);
} }
/// getLoopDepth - Return the loop nesting level of the specified block. A /// getLoopDepth - Return the loop nesting level of the specified block. A
/// depth of 0 means the block is not inside any loop. /// depth of 0 means the block is not inside any loop.
/// ///
@ -687,7 +695,7 @@ class LoopInfoBase {
const LoopT *L = getLoopFor(BB); const LoopT *L = getLoopFor(BB);
return L && L->getHeader() == BB; return L && L->getHeader() == BB;
} }
/// removeLoop - This removes the specified top-level loop from this loop info /// removeLoop - This removes the specified top-level loop from this loop info
/// object. The loop is not deleted, as it will presumably be inserted into /// object. The loop is not deleted, as it will presumably be inserted into
/// another loop. /// another loop.
@ -698,16 +706,20 @@ class LoopInfoBase {
TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin())); TopLevelLoops.erase(TopLevelLoops.begin() + (I-begin()));
return L; return L;
} }
/// changeLoopFor - Change the top-level loop that contains BB to the /// changeLoopFor - Change the top-level loop that contains BB to the
/// specified loop. This should be used by transformations that restructure /// specified loop. This should be used by transformations that restructure
/// the loop hierarchy tree. /// the loop hierarchy tree.
void changeLoopFor(BlockT *BB, LoopT *L) { void changeLoopFor(BlockT *BB, LoopT *L) {
LoopT *&OldLoop = BBMap[BB]; if (!L) {
assert(OldLoop && "Block not in a loop yet!"); typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB);
OldLoop = L; if (I != BBMap.end())
BBMap.erase(I);
return;
}
BBMap[BB] = L;
} }
/// changeTopLevelLoop - Replace the specified loop in the top-level loops /// changeTopLevelLoop - Replace the specified loop in the top-level loops
/// list with the indicated loop. /// list with the indicated loop.
void changeTopLevelLoop(LoopT *OldLoop, void changeTopLevelLoop(LoopT *OldLoop,
@ -719,14 +731,14 @@ class LoopInfoBase {
assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 && assert(NewLoop->ParentLoop == 0 && OldLoop->ParentLoop == 0 &&
"Loops already embedded into a subloop!"); "Loops already embedded into a subloop!");
} }
/// addTopLevelLoop - This adds the specified loop to the collection of /// addTopLevelLoop - This adds the specified loop to the collection of
/// top-level loops. /// top-level loops.
void addTopLevelLoop(LoopT *New) { void addTopLevelLoop(LoopT *New) {
assert(New->getParentLoop() == 0 && "Loop already in subloop!"); assert(New->getParentLoop() == 0 && "Loop already in subloop!");
TopLevelLoops.push_back(New); TopLevelLoops.push_back(New);
} }
/// removeBlock - This method completely removes BB from all data structures, /// removeBlock - This method completely removes BB from all data structures,
/// including all of the Loop objects it is nested in and our mapping from /// including all of the Loop objects it is nested in and our mapping from
/// BasicBlocks to loops. /// BasicBlocks to loops.
@ -739,16 +751,16 @@ class LoopInfoBase {
BBMap.erase(I); BBMap.erase(I);
} }
} }
// Internals // Internals
static bool isNotAlreadyContainedIn(const LoopT *SubLoop, static bool isNotAlreadyContainedIn(const LoopT *SubLoop,
const LoopT *ParentLoop) { const LoopT *ParentLoop) {
if (SubLoop == 0) return true; if (SubLoop == 0) return true;
if (SubLoop == ParentLoop) return false; if (SubLoop == ParentLoop) return false;
return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop); return isNotAlreadyContainedIn(SubLoop->getParentLoop(), ParentLoop);
} }
void Calculate(DominatorTreeBase<BlockT> &DT) { void Calculate(DominatorTreeBase<BlockT> &DT) {
BlockT *RootNode = DT.getRootNode()->getBlock(); BlockT *RootNode = DT.getRootNode()->getBlock();
@ -757,7 +769,7 @@ class LoopInfoBase {
if (LoopT *L = ConsiderForLoop(*NI, DT)) if (LoopT *L = ConsiderForLoop(*NI, DT))
TopLevelLoops.push_back(L); TopLevelLoops.push_back(L);
} }
LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) { LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) {
if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node? if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node?
@ -812,9 +824,9 @@ class LoopInfoBase {
// Normal case, add the block to our loop... // Normal case, add the block to our loop...
L->Blocks.push_back(X); L->Blocks.push_back(X);
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
// Add all of the predecessors of X to the end of the work stack... // Add all of the predecessors of X to the end of the work stack...
TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X), TodoStack.insert(TodoStack.end(), InvBlockTraits::child_begin(X),
InvBlockTraits::child_end(X)); InvBlockTraits::child_end(X));
@ -878,7 +890,7 @@ class LoopInfoBase {
return L; return L;
} }
/// MoveSiblingLoopInto - This method moves the NewChild loop to live inside /// MoveSiblingLoopInto - This method moves the NewChild loop to live inside
/// of the NewParent Loop, instead of being a sibling of it. /// of the NewParent Loop, instead of being a sibling of it.
void MoveSiblingLoopInto(LoopT *NewChild, void MoveSiblingLoopInto(LoopT *NewChild,
@ -897,7 +909,7 @@ class LoopInfoBase {
InsertLoopInto(NewChild, NewParent); InsertLoopInto(NewChild, NewParent);
} }
/// InsertLoopInto - This inserts loop L into the specified parent loop. If /// InsertLoopInto - This inserts loop L into the specified parent loop. If
/// the parent loop contains a loop which should contain L, the loop gets /// the parent loop contains a loop which should contain L, the loop gets
/// inserted into L instead. /// inserted into L instead.
@ -918,9 +930,9 @@ class LoopInfoBase {
Parent->SubLoops.push_back(L); Parent->SubLoops.push_back(L);
L->ParentLoop = Parent; L->ParentLoop = Parent;
} }
// Debugging // Debugging
void print(raw_ostream &OS) const { void print(raw_ostream &OS) const {
for (unsigned i = 0; i < TopLevelLoops.size(); ++i) for (unsigned i = 0; i < TopLevelLoops.size(); ++i)
TopLevelLoops[i]->print(OS); TopLevelLoops[i]->print(OS);
@ -990,7 +1002,7 @@ class LoopInfo : public FunctionPass {
virtual void releaseMemory() { LI.releaseMemory(); } virtual void releaseMemory() { LI.releaseMemory(); }
virtual void print(raw_ostream &O, const Module* M = 0) const; virtual void print(raw_ostream &O, const Module* M = 0) const;
virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual void getAnalysisUsage(AnalysisUsage &AU) const;
/// removeLoop - This removes the specified top-level loop from this loop info /// removeLoop - This removes the specified top-level loop from this loop info
@ -1024,6 +1036,12 @@ class LoopInfo : public FunctionPass {
LI.removeBlock(BB); LI.removeBlock(BB);
} }
/// updateUnloop - Update LoopInfo after removing the last backedge from a
/// loop--now the "unloop". This updates the loop forest and parent loops for
/// each block so that Unloop is no longer referenced, but the caller must
/// actually delete the Unloop object.
void updateUnloop(Loop *Unloop);
/// replacementPreservesLCSSAForm - Returns true if replacing From with To /// replacementPreservesLCSSAForm - Returns true if replacing From with To
/// everywhere is guaranteed to preserve LCSSA form. /// everywhere is guaranteed to preserve LCSSA form.
bool replacementPreservesLCSSAForm(Instruction *From, Value *To) { bool replacementPreservesLCSSAForm(Instruction *From, Value *To) {

View File

@ -0,0 +1,186 @@
//===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// This file defines iterators to visit the basic blocks within a loop.
//
// These iterators currently visit blocks within subloops as well.
// Unfortunately we have no efficient way of summarizing loop exits which would
// allow skipping subloops during traversal.
//
// If you want to visit all blocks in a loop and don't need an ordered traveral,
// use Loop::block_begin() instead.
//
// This is intentionally designed to work with ill-formed loops in which the
// backedge has been deleted. The only prerequisite is that all blocks
// contained within the loop according to the most recent LoopInfo analysis are
// reachable from the loop header.
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_LOOP_ITERATOR_H
#define LLVM_ANALYSIS_LOOP_ITERATOR_H
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/Analysis/LoopInfo.h"
namespace llvm {
class LoopBlocksTraversal;
/// Store the result of a depth first search within basic blocks contained by a
/// single loop.
///
/// TODO: This could be generalized for any CFG region, or the entire CFG.
class LoopBlocksDFS {
public:
/// Postorder list iterators.
typedef std::vector<BasicBlock*>::const_iterator POIterator;
typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
friend class LoopBlocksTraversal;
private:
Loop *L;
/// Map each block to its postorder number. A block is only mapped after it is
/// preorder visited by DFS. It's postorder number is initially zero and set
/// to nonzero after it is finished by postorder traversal.
DenseMap<BasicBlock*, unsigned> PostNumbers;
std::vector<BasicBlock*> PostBlocks;
public:
LoopBlocksDFS(Loop *Container) :
L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
PostBlocks.reserve(Container->getNumBlocks());
}
Loop *getLoop() const { return L; }
/// Traverse the loop blocks and store the DFS result.
void perform(LoopInfo *LI);
/// Return true if postorder numbers are assigned to all loop blocks.
bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
/// Iterate over the cached postorder blocks.
POIterator beginPostorder() const {
assert(isComplete() && "bad loop DFS");
return PostBlocks.begin();
}
POIterator endPostorder() const { return PostBlocks.end(); }
/// Reverse iterate over the cached postorder blocks.
RPOIterator beginRPO() const {
assert(isComplete() && "bad loop DFS");
return PostBlocks.rbegin();
}
RPOIterator endRPO() const { return PostBlocks.rend(); }
/// Return true if this block has been preorder visited.
bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
/// Return true if this block has a postorder number.
bool hasPostorder(BasicBlock *BB) const {
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
return I != PostNumbers.end() && I->second;
}
/// Get a block's postorder number.
unsigned getPostorder(BasicBlock *BB) const {
DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
assert(I != PostNumbers.end() && "block not visited by DFS");
assert(I->second && "block not finished by DFS");
return I->second;
}
/// Get a block's reverse postorder number.
unsigned getRPO(BasicBlock *BB) const {
return 1 + PostBlocks.size() - getPostorder(BB);
}
void clear() {
PostNumbers.clear();
PostBlocks.clear();
}
};
/// Traverse the blocks in a loop using a depth-first search.
class LoopBlocksTraversal {
public:
/// Graph traversal iterator.
typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
private:
LoopBlocksDFS &DFS;
LoopInfo *LI;
public:
LoopBlocksTraversal(LoopBlocksDFS &Storage, LoopInfo *LInfo) :
DFS(Storage), LI(LInfo) {}
/// Postorder traversal over the graph. This only needs to be done once.
/// po_iterator "automatically" calls back to visitPreorder and
/// finishPostorder to record the DFS result.
POTIterator begin() {
assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
return po_ext_begin(DFS.L->getHeader(), *this);
}
POTIterator end() {
// po_ext_end interface requires a basic block, but ignores its value.
return po_ext_end(DFS.L->getHeader(), *this);
}
/// Called by po_iterator upon reaching a block via a CFG edge. If this block
/// is contained in the loop and has not been visited, then mark it preorder
/// visited and return true.
///
/// TODO: If anyone is interested, we could record preorder numbers here.
bool visitPreorder(BasicBlock *BB) {
if (!DFS.L->contains(LI->getLoopFor(BB)))
return false;
return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
}
/// Called by po_iterator each time it advances, indicating a block's
/// postorder.
void finishPostorder(BasicBlock *BB) {
assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
DFS.PostBlocks.push_back(BB);
DFS.PostNumbers[BB] = DFS.PostBlocks.size();
}
//===----------------------------------------------------------------------
// Implement part of the std::set interface for the purpose of driving the
// generic po_iterator.
/// Return true if the block is outside the loop or has already been visited.
/// Sorry if this is counterintuitive.
bool count(BasicBlock *BB) const {
return !DFS.L->contains(LI->getLoopFor(BB)) || DFS.PostNumbers.count(BB);
}
/// If this block is contained in the loop and has not been visited, return
/// true and assign a preorder number. This is a proxy for visitPreorder
/// called by POIterator.
bool insert(BasicBlock *BB) {
return visitPreorder(BB);
}
};
/// Specialize DFSetTraits to record postorder numbers.
template<> struct DFSetTraits<LoopBlocksTraversal> {
static void finishPostorder(BasicBlock *BB, LoopBlocksTraversal& LBT) {
LBT.finishPostorder(BB);
}
};
} // End namespace llvm
#endif

View File

@ -84,7 +84,7 @@ class LoopPass : public Pass {
class LPPassManager : public FunctionPass, public PMDataManager { class LPPassManager : public FunctionPass, public PMDataManager {
public: public:
static char ID; static char ID;
explicit LPPassManager(int Depth); explicit LPPassManager();
/// run - Execute all of the passes scheduled for execution. Keep track of /// run - Execute all of the passes scheduled for execution. Keep track of
/// whether any of the passes modifies the module, and if so, return true. /// whether any of the passes modifies the module, and if so, return true.

View File

@ -51,14 +51,14 @@ const CallInst *isArrayMalloc(const Value *I, const TargetData *TD);
/// 0: PointerType is the malloc calls' return type. /// 0: PointerType is the malloc calls' return type.
/// 1: PointerType is the bitcast's result type. /// 1: PointerType is the bitcast's result type.
/// >1: Unique PointerType cannot be determined, return NULL. /// >1: Unique PointerType cannot be determined, return NULL.
const PointerType *getMallocType(const CallInst *CI); PointerType *getMallocType(const CallInst *CI);
/// getMallocAllocatedType - Returns the Type allocated by malloc call. /// getMallocAllocatedType - Returns the Type allocated by malloc call.
/// The Type depends on the number of bitcast uses of the malloc call: /// The Type depends on the number of bitcast uses of the malloc call:
/// 0: PointerType is the malloc calls' return type. /// 0: PointerType is the malloc calls' return type.
/// 1: PointerType is the bitcast's result type. /// 1: PointerType is the bitcast's result type.
/// >1: Unique PointerType cannot be determined, return NULL. /// >1: Unique PointerType cannot be determined, return NULL.
const Type *getMallocAllocatedType(const CallInst *CI); Type *getMallocAllocatedType(const CallInst *CI);
/// getMallocArraySize - Returns the array size of a malloc call. If the /// getMallocArraySize - Returns the array size of a malloc call. If the
/// argument passed to malloc is a multiple of the size of the malloced type, /// argument passed to malloc is a multiple of the size of the malloced type,

View File

@ -52,9 +52,6 @@ namespace llvm {
/// 1. Loads are clobbered by may-alias stores. /// 1. Loads are clobbered by may-alias stores.
/// 2. Loads are considered clobbered by partially-aliased loads. The /// 2. Loads are considered clobbered by partially-aliased loads. The
/// client may choose to analyze deeper into these cases. /// client may choose to analyze deeper into these cases.
///
/// A dependence query on the first instruction of the entry block will
/// return a clobber(self) result.
Clobber, Clobber,
/// Def - This is a dependence on the specified instruction which /// Def - This is a dependence on the specified instruction which
@ -76,11 +73,27 @@ namespace llvm {
/// operands to the calls are the same. /// operands to the calls are the same.
Def, Def,
/// Other - This marker indicates that the query has no known dependency
/// in the specified block. More detailed state info is encoded in the
/// upper part of the pair (i.e. the Instruction*)
Other
};
/// If DepType is "Other", the upper part of the pair
/// (i.e. the Instruction* part) is instead used to encode more detailed
/// type information as follows
enum OtherType {
/// NonLocal - This marker indicates that the query has no dependency in /// NonLocal - This marker indicates that the query has no dependency in
/// the specified block. To find out more, the client should query other /// the specified block. To find out more, the client should query other
/// predecessor blocks. /// predecessor blocks.
NonLocal NonLocal = 0x4,
/// NonFuncLocal - This marker indicates that the query has no
/// dependency in the specified function.
NonFuncLocal = 0x8,
/// Unknown - This marker indicates that the query dependency
/// is unknown.
Unknown = 0xc
}; };
typedef PointerIntPair<Instruction*, 2, DepType> PairTy; typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
PairTy Value; PairTy Value;
explicit MemDepResult(PairTy V) : Value(V) {} explicit MemDepResult(PairTy V) : Value(V) {}
@ -98,19 +111,21 @@ namespace llvm {
return MemDepResult(PairTy(Inst, Clobber)); return MemDepResult(PairTy(Inst, Clobber));
} }
static MemDepResult getNonLocal() { static MemDepResult getNonLocal() {
return MemDepResult(PairTy(0, NonLocal)); return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonLocal), Other));
}
static MemDepResult getNonFuncLocal() {
return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
} }
static MemDepResult getUnknown() { static MemDepResult getUnknown() {
return MemDepResult(PairTy(0, Clobber)); return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(Unknown), Other));
} }
/// isClobber - Return true if this MemDepResult represents a query that is /// isClobber - Return true if this MemDepResult represents a query that is
/// a instruction clobber dependency. /// a instruction clobber dependency.
bool isClobber() const { return Value.getInt() == Clobber && getInst(); } bool isClobber() const { return Value.getInt() == Clobber; }
/// isUnknown - Return true if this MemDepResult represents a query which
/// cannot and/or will not be computed.
bool isUnknown() const { return Value.getInt() == Clobber && !getInst(); }
/// isDef - Return true if this MemDepResult represents a query that is /// isDef - Return true if this MemDepResult represents a query that is
/// a instruction definition dependency. /// a instruction definition dependency.
@ -119,11 +134,31 @@ namespace llvm {
/// isNonLocal - Return true if this MemDepResult represents a query that /// isNonLocal - Return true if this MemDepResult represents a query that
/// is transparent to the start of the block, but where a non-local hasn't /// is transparent to the start of the block, but where a non-local hasn't
/// been done. /// been done.
bool isNonLocal() const { return Value.getInt() == NonLocal; } bool isNonLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonLocal);
}
/// isNonFuncLocal - Return true if this MemDepResult represents a query
/// that is transparent to the start of the function.
bool isNonFuncLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal);
}
/// isUnknown - Return true if this MemDepResult represents a query which
/// cannot and/or will not be computed.
bool isUnknown() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(Unknown);
}
/// getInst() - If this is a normal dependency, return the instruction that /// getInst() - If this is a normal dependency, return the instruction that
/// is depended on. Otherwise, return null. /// is depended on. Otherwise, return null.
Instruction *getInst() const { return Value.getPointer(); } Instruction *getInst() const {
if (Value.getInt() == Other) return NULL;
return Value.getPointer();
}
bool operator==(const MemDepResult &M) const { return Value == M.Value; } bool operator==(const MemDepResult &M) const { return Value == M.Value; }
bool operator!=(const MemDepResult &M) const { return Value != M.Value; } bool operator!=(const MemDepResult &M) const { return Value != M.Value; }

View File

@ -88,7 +88,7 @@ class RGPassManager : public FunctionPass, public PMDataManager {
public: public:
static char ID; static char ID;
explicit RGPassManager(int Depth); explicit RGPassManager();
/// @brief Execute all of the passes scheduled for execution. /// @brief Execute all of the passes scheduled for execution.
/// ///

View File

@ -103,7 +103,7 @@ namespace llvm {
/// getType - Return the LLVM type of this SCEV expression. /// getType - Return the LLVM type of this SCEV expression.
/// ///
const Type *getType() const; Type *getType() const;
/// isZero - Return true if the expression is a constant zero. /// isZero - Return true if the expression is a constant zero.
/// ///
@ -241,31 +241,94 @@ namespace llvm {
/// ///
ValueExprMapType ValueExprMap; ValueExprMapType ValueExprMap;
/// ExitLimit - Information about the number of loop iterations for
/// which a loop exit's branch condition evaluates to the not-taken path.
/// This is a temporary pair of exact and max expressions that are
/// eventually summarized in ExitNotTakenInfo and BackedgeTakenInfo.
struct ExitLimit {
const SCEV *Exact;
const SCEV *Max;
/*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {}
ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {}
/// hasAnyInfo - Test whether this ExitLimit contains any computed
/// information, or whether it's all SCEVCouldNotCompute values.
bool hasAnyInfo() const {
return !isa<SCEVCouldNotCompute>(Exact) ||
!isa<SCEVCouldNotCompute>(Max);
}
};
/// ExitNotTakenInfo - Information about the number of times a particular
/// loop exit may be reached before exiting the loop.
struct ExitNotTakenInfo {
AssertingVH<BasicBlock> ExitingBlock;
const SCEV *ExactNotTaken;
PointerIntPair<ExitNotTakenInfo*, 1> NextExit;
ExitNotTakenInfo() : ExitingBlock(0), ExactNotTaken(0) {}
/// isCompleteList - Return true if all loop exits are computable.
bool isCompleteList() const {
return NextExit.getInt() == 0;
}
void setIncomplete() { NextExit.setInt(1); }
/// getNextExit - Return a pointer to the next exit's not-taken info.
ExitNotTakenInfo *getNextExit() const {
return NextExit.getPointer();
}
void setNextExit(ExitNotTakenInfo *ENT) { NextExit.setPointer(ENT); }
};
/// BackedgeTakenInfo - Information about the backedge-taken count /// BackedgeTakenInfo - Information about the backedge-taken count
/// of a loop. This currently includes an exact count and a maximum count. /// of a loop. This currently includes an exact count and a maximum count.
/// ///
struct BackedgeTakenInfo { class BackedgeTakenInfo {
/// Exact - An expression indicating the exact backedge-taken count of /// ExitNotTaken - A list of computable exits and their not-taken counts.
/// the loop if it is known, or a SCEVCouldNotCompute otherwise. /// Loops almost never have more than one computable exit.
const SCEV *Exact; ExitNotTakenInfo ExitNotTaken;
/// Max - An expression indicating the least maximum backedge-taken /// Max - An expression indicating the least maximum backedge-taken
/// count of the loop that is known, or a SCEVCouldNotCompute. /// count of the loop that is known, or a SCEVCouldNotCompute.
const SCEV *Max; const SCEV *Max;
/*implicit*/ BackedgeTakenInfo(const SCEV *exact) : public:
Exact(exact), Max(exact) {} BackedgeTakenInfo() : Max(0) {}
BackedgeTakenInfo(const SCEV *exact, const SCEV *max) : /// Initialize BackedgeTakenInfo from a list of exact exit counts.
Exact(exact), Max(max) {} BackedgeTakenInfo(
SmallVectorImpl< std::pair<BasicBlock *, const SCEV *> > &ExitCounts,
bool Complete, const SCEV *MaxCount);
/// hasAnyInfo - Test whether this BackedgeTakenInfo contains any /// hasAnyInfo - Test whether this BackedgeTakenInfo contains any
/// computed information, or whether it's all SCEVCouldNotCompute /// computed information, or whether it's all SCEVCouldNotCompute
/// values. /// values.
bool hasAnyInfo() const { bool hasAnyInfo() const {
return !isa<SCEVCouldNotCompute>(Exact) || return ExitNotTaken.ExitingBlock || !isa<SCEVCouldNotCompute>(Max);
!isa<SCEVCouldNotCompute>(Max);
} }
/// getExact - Return an expression indicating the exact backedge-taken
/// count of the loop if it is known, or SCEVCouldNotCompute
/// otherwise. This is the number of times the loop header can be
/// guaranteed to execute, minus one.
const SCEV *getExact(ScalarEvolution *SE) const;
/// getExact - Return the number of times this loop exit may fall through
/// to the back edge, or SCEVCouldNotCompute. The loop is guaranteed not
/// to exit via this block before this number of iterations, but may exit
/// via another block.
const SCEV *getExact(BasicBlock *ExitingBlock, ScalarEvolution *SE) const;
/// getMax - Get the max backedge taken count for the loop.
const SCEV *getMax(ScalarEvolution *SE) const;
/// clear - Invalidate this result and free associated memory.
void clear();
}; };
/// BackedgeTakenCounts - Cache the backedge-taken count of the loops for /// BackedgeTakenCounts - Cache the backedge-taken count of the loops for
@ -365,64 +428,59 @@ namespace llvm {
/// loop will iterate. /// loop will iterate.
BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L); BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L);
/// ComputeBackedgeTakenCountFromExit - Compute the number of times the /// ComputeExitLimit - Compute the number of times the backedge of the
/// backedge of the specified loop will execute if it exits via the /// specified loop will execute if it exits via the specified block.
/// specified block. ExitLimit ComputeExitLimit(const Loop *L, BasicBlock *ExitingBlock);
BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L,
BasicBlock *ExitingBlock);
/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the /// ComputeExitLimitFromCond - Compute the number of times the backedge of
/// backedge of the specified loop will execute if its exit condition /// the specified loop will execute if its exit condition were a conditional
/// were a conditional branch of ExitCond, TBB, and FBB. /// branch of ExitCond, TBB, and FBB.
BackedgeTakenInfo ExitLimit ComputeExitLimitFromCond(const Loop *L,
ComputeBackedgeTakenCountFromExitCond(const Loop *L, Value *ExitCond,
Value *ExitCond, BasicBlock *TBB,
BasicBlock *TBB, BasicBlock *FBB);
BasicBlock *FBB);
/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of /// ComputeExitLimitFromICmp - Compute the number of times the backedge of
/// times the backedge of the specified loop will execute if its exit /// the specified loop will execute if its exit condition were a conditional
/// condition were a conditional branch of the ICmpInst ExitCond, TBB, /// branch of the ICmpInst ExitCond, TBB, and FBB.
/// and FBB. ExitLimit ComputeExitLimitFromICmp(const Loop *L,
BackedgeTakenInfo ICmpInst *ExitCond,
ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, BasicBlock *TBB,
ICmpInst *ExitCond, BasicBlock *FBB);
BasicBlock *TBB,
BasicBlock *FBB);
/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition /// ComputeLoadConstantCompareExitLimit - Given an exit condition
/// of 'icmp op load X, cst', try to see if we can compute the /// of 'icmp op load X, cst', try to see if we can compute the
/// backedge-taken count. /// backedge-taken count.
BackedgeTakenInfo ExitLimit ComputeLoadConstantCompareExitLimit(LoadInst *LI,
ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS,
Constant *RHS, const Loop *L,
const Loop *L, ICmpInst::Predicate p);
ICmpInst::Predicate p);
/// ComputeBackedgeTakenCountExhaustively - If the loop is known to execute /// ComputeExitCountExhaustively - If the loop is known to execute a
/// a constant number of times (the condition evolves only from constants), /// constant number of times (the condition evolves only from constants),
/// try to evaluate a few iterations of the loop until we get the exit /// try to evaluate a few iterations of the loop until we get the exit
/// condition gets a value of ExitWhen (true or false). If we cannot /// condition gets a value of ExitWhen (true or false). If we cannot
/// evaluate the backedge-taken count of the loop, return CouldNotCompute. /// evaluate the exit count of the loop, return CouldNotCompute.
const SCEV *ComputeBackedgeTakenCountExhaustively(const Loop *L, const SCEV *ComputeExitCountExhaustively(const Loop *L,
Value *Cond, Value *Cond,
bool ExitWhen); bool ExitWhen);
/// HowFarToZero - Return the number of times a backedge comparing the /// HowFarToZero - Return the number of times an exit condition comparing
/// specified value to zero will execute. If not computable, return /// the specified value to zero will execute. If not computable, return
/// CouldNotCompute. /// CouldNotCompute.
BackedgeTakenInfo HowFarToZero(const SCEV *V, const Loop *L); ExitLimit HowFarToZero(const SCEV *V, const Loop *L);
/// HowFarToNonZero - Return the number of times a backedge checking the /// HowFarToNonZero - Return the number of times an exit condition checking
/// specified value for nonzero will execute. If not computable, return /// the specified value for nonzero will execute. If not computable, return
/// CouldNotCompute. /// CouldNotCompute.
BackedgeTakenInfo HowFarToNonZero(const SCEV *V, const Loop *L); ExitLimit HowFarToNonZero(const SCEV *V, const Loop *L);
/// HowManyLessThans - Return the number of times a backedge containing the /// HowManyLessThans - Return the number of times an exit condition
/// specified less-than comparison will execute. If not computable, return /// containing the specified less-than comparison will execute. If not
/// CouldNotCompute. isSigned specifies whether the less-than is signed. /// computable, return CouldNotCompute. isSigned specifies whether the
BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS, /// less-than is signed.
const Loop *L, bool isSigned); ExitLimit HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
const Loop *L, bool isSigned);
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB /// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
/// (which may not be an immediate predecessor) which has exactly one /// (which may not be an immediate predecessor) which has exactly one
@ -450,7 +508,8 @@ namespace llvm {
/// FoundLHS, and FoundRHS is true. /// FoundLHS, and FoundRHS is true.
bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS, const SCEV *LHS, const SCEV *RHS,
const SCEV *FoundLHS, const SCEV *FoundRHS); const SCEV *FoundLHS,
const SCEV *FoundRHS);
/// getConstantEvolutionLoopExitValue - If we know that the specified Phi is /// getConstantEvolutionLoopExitValue - If we know that the specified Phi is
/// in the header of its containing loop, we know the loop executes a /// in the header of its containing loop, we know the loop executes a
@ -479,17 +538,17 @@ namespace llvm {
/// the SCEV framework. This primarily includes integer types, and it /// the SCEV framework. This primarily includes integer types, and it
/// can optionally include pointer types if the ScalarEvolution class /// can optionally include pointer types if the ScalarEvolution class
/// has access to target-specific information. /// has access to target-specific information.
bool isSCEVable(const Type *Ty) const; bool isSCEVable(Type *Ty) const;
/// getTypeSizeInBits - Return the size in bits of the specified type, /// getTypeSizeInBits - Return the size in bits of the specified type,
/// for which isSCEVable must return true. /// for which isSCEVable must return true.
uint64_t getTypeSizeInBits(const Type *Ty) const; uint64_t getTypeSizeInBits(Type *Ty) const;
/// getEffectiveSCEVType - Return a type with the same bitwidth as /// getEffectiveSCEVType - Return a type with the same bitwidth as
/// the given type and which represents how SCEV will treat the given /// the given type and which represents how SCEV will treat the given
/// type, for which isSCEVable must return true. For pointer types, /// type, for which isSCEVable must return true. For pointer types,
/// this is the pointer-sized integer type. /// this is the pointer-sized integer type.
const Type *getEffectiveSCEVType(const Type *Ty) const; Type *getEffectiveSCEVType(Type *Ty) const;
/// getSCEV - Return a SCEV expression for the full generality of the /// getSCEV - Return a SCEV expression for the full generality of the
/// specified expression. /// specified expression.
@ -497,11 +556,11 @@ namespace llvm {
const SCEV *getConstant(ConstantInt *V); const SCEV *getConstant(ConstantInt *V);
const SCEV *getConstant(const APInt& Val); const SCEV *getConstant(const APInt& Val);
const SCEV *getConstant(const Type *Ty, uint64_t V, bool isSigned = false); const SCEV *getConstant(Type *Ty, uint64_t V, bool isSigned = false);
const SCEV *getTruncateExpr(const SCEV *Op, const Type *Ty); const SCEV *getTruncateExpr(const SCEV *Op, Type *Ty);
const SCEV *getZeroExtendExpr(const SCEV *Op, const Type *Ty); const SCEV *getZeroExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getSignExtendExpr(const SCEV *Op, const Type *Ty); const SCEV *getSignExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAnyExtendExpr(const SCEV *Op, const Type *Ty); const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops, const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap); SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap);
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS, const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
@ -529,6 +588,14 @@ namespace llvm {
Ops.push_back(RHS); Ops.push_back(RHS);
return getMulExpr(Ops, Flags); return getMulExpr(Ops, Flags);
} }
const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap) {
SmallVector<const SCEV *, 3> Ops;
Ops.push_back(Op0);
Ops.push_back(Op1);
Ops.push_back(Op2);
return getMulExpr(Ops, Flags);
}
const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS); const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step, const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step,
const Loop *L, SCEV::NoWrapFlags Flags); const Loop *L, SCEV::NoWrapFlags Flags);
@ -550,19 +617,19 @@ namespace llvm {
/// getSizeOfExpr - Return an expression for sizeof on the given type. /// getSizeOfExpr - Return an expression for sizeof on the given type.
/// ///
const SCEV *getSizeOfExpr(const Type *AllocTy); const SCEV *getSizeOfExpr(Type *AllocTy);
/// getAlignOfExpr - Return an expression for alignof on the given type. /// getAlignOfExpr - Return an expression for alignof on the given type.
/// ///
const SCEV *getAlignOfExpr(const Type *AllocTy); const SCEV *getAlignOfExpr(Type *AllocTy);
/// getOffsetOfExpr - Return an expression for offsetof on the given field. /// getOffsetOfExpr - Return an expression for offsetof on the given field.
/// ///
const SCEV *getOffsetOfExpr(const StructType *STy, unsigned FieldNo); const SCEV *getOffsetOfExpr(StructType *STy, unsigned FieldNo);
/// getOffsetOfExpr - Return an expression for offsetof on the given field. /// getOffsetOfExpr - Return an expression for offsetof on the given field.
/// ///
const SCEV *getOffsetOfExpr(const Type *CTy, Constant *FieldNo); const SCEV *getOffsetOfExpr(Type *CTy, Constant *FieldNo);
/// getNegativeSCEV - Return the SCEV object corresponding to -V. /// getNegativeSCEV - Return the SCEV object corresponding to -V.
/// ///
@ -579,33 +646,33 @@ namespace llvm {
/// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion /// getTruncateOrZeroExtend - Return a SCEV corresponding to a conversion
/// of the input value to the specified type. If the type must be /// of the input value to the specified type. If the type must be
/// extended, it is zero extended. /// extended, it is zero extended.
const SCEV *getTruncateOrZeroExtend(const SCEV *V, const Type *Ty); const SCEV *getTruncateOrZeroExtend(const SCEV *V, Type *Ty);
/// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion /// getTruncateOrSignExtend - Return a SCEV corresponding to a conversion
/// of the input value to the specified type. If the type must be /// of the input value to the specified type. If the type must be
/// extended, it is sign extended. /// extended, it is sign extended.
const SCEV *getTruncateOrSignExtend(const SCEV *V, const Type *Ty); const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty);
/// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of /// getNoopOrZeroExtend - Return a SCEV corresponding to a conversion of
/// the input value to the specified type. If the type must be extended, /// the input value to the specified type. If the type must be extended,
/// it is zero extended. The conversion must not be narrowing. /// it is zero extended. The conversion must not be narrowing.
const SCEV *getNoopOrZeroExtend(const SCEV *V, const Type *Ty); const SCEV *getNoopOrZeroExtend(const SCEV *V, Type *Ty);
/// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of /// getNoopOrSignExtend - Return a SCEV corresponding to a conversion of
/// the input value to the specified type. If the type must be extended, /// the input value to the specified type. If the type must be extended,
/// it is sign extended. The conversion must not be narrowing. /// it is sign extended. The conversion must not be narrowing.
const SCEV *getNoopOrSignExtend(const SCEV *V, const Type *Ty); const SCEV *getNoopOrSignExtend(const SCEV *V, Type *Ty);
/// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of /// getNoopOrAnyExtend - Return a SCEV corresponding to a conversion of
/// the input value to the specified type. If the type must be extended, /// the input value to the specified type. If the type must be extended,
/// it is extended with unspecified bits. The conversion must not be /// it is extended with unspecified bits. The conversion must not be
/// narrowing. /// narrowing.
const SCEV *getNoopOrAnyExtend(const SCEV *V, const Type *Ty); const SCEV *getNoopOrAnyExtend(const SCEV *V, Type *Ty);
/// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the /// getTruncateOrNoop - Return a SCEV corresponding to a conversion of the
/// input value to the specified type. The conversion must not be /// input value to the specified type. The conversion must not be
/// widening. /// widening.
const SCEV *getTruncateOrNoop(const SCEV *V, const Type *Ty); const SCEV *getTruncateOrNoop(const SCEV *V, Type *Ty);
/// getUMaxFromMismatchedTypes - Promote the operands to the wider of /// getUMaxFromMismatchedTypes - Promote the operands to the wider of
/// the types using zero-extension, and then perform a umax operation /// the types using zero-extension, and then perform a umax operation
@ -653,6 +720,23 @@ namespace llvm {
bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS); const SCEV *LHS, const SCEV *RHS);
/// getSmallConstantTripCount - Returns the maximum trip count of this loop
/// as a normal unsigned value, if possible. Returns 0 if the trip count is
/// unknown or not constant.
unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitBlock);
/// getSmallConstantTripMultiple - Returns the largest constant divisor of
/// the trip count of this loop as a normal unsigned value, if
/// possible. This means that the actual trip count is always a multiple of
/// the returned value (don't forget the trip count could very well be zero
/// as well!).
unsigned getSmallConstantTripMultiple(Loop *L, BasicBlock *ExitBlock);
// getExitCount - Get the expression for the number of loop iterations for
// which this loop is guaranteed not to exit via ExitingBlock. Otherwise
// return SCEVCouldNotCompute.
const SCEV *getExitCount(Loop *L, BasicBlock *ExitingBlock);
/// getBackedgeTakenCount - If the specified loop has a predictable /// getBackedgeTakenCount - If the specified loop has a predictable
/// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute /// backedge-taken count, return it, otherwise return a SCEVCouldNotCompute
/// object. The backedge-taken count is the number of times the loop header /// object. The backedge-taken count is the number of times the loop header

View File

@ -64,16 +64,34 @@ namespace llvm {
/// in a more literal form. /// in a more literal form.
bool CanonicalMode; bool CanonicalMode;
/// When invoked from LSR, the expander is in "strength reduction" mode. The
/// only difference is that phi's are only reused if they are already in
/// "expanded" form.
bool LSRMode;
typedef IRBuilder<true, TargetFolder> BuilderType; typedef IRBuilder<true, TargetFolder> BuilderType;
BuilderType Builder; BuilderType Builder;
#ifndef NDEBUG
const char *DebugType;
#endif
friend struct SCEVVisitor<SCEVExpander, Value*>; friend struct SCEVVisitor<SCEVExpander, Value*>;
public: public:
/// SCEVExpander - Construct a SCEVExpander in "canonical" mode. /// SCEVExpander - Construct a SCEVExpander in "canonical" mode.
explicit SCEVExpander(ScalarEvolution &se, const char *name) explicit SCEVExpander(ScalarEvolution &se, const char *name)
: SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0), : SE(se), IVName(name), IVIncInsertLoop(0), IVIncInsertPos(0),
CanonicalMode(true), Builder(se.getContext(), TargetFolder(se.TD)) {} CanonicalMode(true), LSRMode(false),
Builder(se.getContext(), TargetFolder(se.TD)) {
#ifndef NDEBUG
DebugType = "";
#endif
}
#ifndef NDEBUG
void setDebugType(const char* s) { DebugType = s; }
#endif
/// clear - Erase the contents of the InsertedExpressions map so that users /// clear - Erase the contents of the InsertedExpressions map so that users
/// trying to expand the same expression into multiple BasicBlocks or /// trying to expand the same expression into multiple BasicBlocks or
@ -88,13 +106,21 @@ namespace llvm {
/// canonical induction variable of the specified type for the specified /// canonical induction variable of the specified type for the specified
/// loop (inserting one if there is none). A canonical induction variable /// loop (inserting one if there is none). A canonical induction variable
/// starts at zero and steps by one on each iteration. /// starts at zero and steps by one on each iteration.
PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty);
const Type *Ty);
/// hoistStep - Utility for hoisting an IV increment.
static bool hoistStep(Instruction *IncV, Instruction *InsertPos,
const DominatorTree *DT);
/// replaceCongruentIVs - replace congruent phis with their most canonical
/// representative. Return the number of phis eliminated.
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
SmallVectorImpl<WeakVH> &DeadInsts);
/// expandCodeFor - Insert code to directly compute the specified SCEV /// expandCodeFor - Insert code to directly compute the specified SCEV
/// expression into the program. The inserted code is inserted into the /// expression into the program. The inserted code is inserted into the
/// specified block. /// specified block.
Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I); Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I);
/// setIVIncInsertPos - Set the current IV increment loop and position. /// setIVIncInsertPos - Set the current IV increment loop and position.
void setIVIncInsertPos(const Loop *L, Instruction *Pos) { void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
@ -127,13 +153,14 @@ namespace llvm {
/// is useful for late optimization passes. /// is useful for late optimization passes.
void disableCanonicalMode() { CanonicalMode = false; } void disableCanonicalMode() { CanonicalMode = false; }
void enableLSRMode() { LSRMode = true; }
/// clearInsertPoint - Clear the current insertion point. This is useful /// clearInsertPoint - Clear the current insertion point. This is useful
/// if the instruction that had been serving as the insertion point may /// if the instruction that had been serving as the insertion point may
/// have been deleted. /// have been deleted.
void clearInsertPoint() { void clearInsertPoint() {
Builder.ClearInsertionPoint(); Builder.ClearInsertionPoint();
} }
private: private:
LLVMContext &getContext() const { return SE.getContext(); } LLVMContext &getContext() const { return SE.getContext(); }
@ -145,20 +172,20 @@ namespace llvm {
/// reusing an existing cast if a suitable one exists, moving an existing /// reusing an existing cast if a suitable one exists, moving an existing
/// cast if a suitable one exists but isn't in the right place, or /// cast if a suitable one exists but isn't in the right place, or
/// or creating a new one. /// or creating a new one.
Value *ReuseOrCreateCast(Value *V, const Type *Ty, Value *ReuseOrCreateCast(Value *V, Type *Ty,
Instruction::CastOps Op, Instruction::CastOps Op,
BasicBlock::iterator IP); BasicBlock::iterator IP);
/// InsertNoopCastOfTo - Insert a cast of V to the specified type, /// InsertNoopCastOfTo - Insert a cast of V to the specified type,
/// which must be possible with a noop cast, doing what we can to /// which must be possible with a noop cast, doing what we can to
/// share the casts. /// share the casts.
Value *InsertNoopCastOfTo(Value *V, const Type *Ty); Value *InsertNoopCastOfTo(Value *V, Type *Ty);
/// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP
/// instead of using ptrtoint+arithmetic+inttoptr. /// instead of using ptrtoint+arithmetic+inttoptr.
Value *expandAddToGEP(const SCEV *const *op_begin, Value *expandAddToGEP(const SCEV *const *op_begin,
const SCEV *const *op_end, const SCEV *const *op_end,
const PointerType *PTy, const Type *Ty, Value *V); PointerType *PTy, Type *Ty, Value *V);
Value *expand(const SCEV *S); Value *expand(const SCEV *S);
@ -166,7 +193,7 @@ namespace llvm {
/// expression into the program. The inserted code is inserted into the /// expression into the program. The inserted code is inserted into the
/// SCEVExpander's current insertion point. If a type is specified, the /// SCEVExpander's current insertion point. If a type is specified, the
/// result will be expanded to have that type, with a cast if necessary. /// result will be expanded to have that type, with a cast if necessary.
Value *expandCodeFor(const SCEV *SH, const Type *Ty = 0); Value *expandCodeFor(const SCEV *SH, Type *Ty = 0);
/// isInsertedInstruction - Return true if the specified instruction was /// isInsertedInstruction - Return true if the specified instruction was
/// inserted by the code rewriter. If so, the client should not modify the /// inserted by the code rewriter. If so, the client should not modify the
@ -208,11 +235,15 @@ namespace llvm {
void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I); void restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I);
bool isNormalAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
bool isExpandedAddRecExprPHI(PHINode *PN, Instruction *IncV, const Loop *L);
Value *expandAddRecExprLiterally(const SCEVAddRecExpr *); Value *expandAddRecExprLiterally(const SCEVAddRecExpr *);
PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, PHINode *getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized,
const Loop *L, const Loop *L,
const Type *ExpandTy, Type *ExpandTy,
const Type *IntTy); Type *IntTy);
}; };
} }

View File

@ -42,7 +42,7 @@ namespace llvm {
public: public:
ConstantInt *getValue() const { return V; } ConstantInt *getValue() const { return V; }
const Type *getType() const { return V->getType(); } Type *getType() const { return V->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVConstant *S) { return true; } static inline bool classof(const SCEVConstant *S) { return true; }
@ -57,14 +57,14 @@ namespace llvm {
class SCEVCastExpr : public SCEV { class SCEVCastExpr : public SCEV {
protected: protected:
const SCEV *Op; const SCEV *Op;
const Type *Ty; Type *Ty;
SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVCastExpr(const FoldingSetNodeIDRef ID,
unsigned SCEVTy, const SCEV *op, const Type *ty); unsigned SCEVTy, const SCEV *op, Type *ty);
public: public:
const SCEV *getOperand() const { return Op; } const SCEV *getOperand() const { return Op; }
const Type *getType() const { return Ty; } Type *getType() const { return Ty; }
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVCastExpr *S) { return true; } static inline bool classof(const SCEVCastExpr *S) { return true; }
@ -83,7 +83,7 @@ namespace llvm {
friend class ScalarEvolution; friend class ScalarEvolution;
SCEVTruncateExpr(const FoldingSetNodeIDRef ID, SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
const SCEV *op, const Type *ty); const SCEV *op, Type *ty);
public: public:
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -101,7 +101,7 @@ namespace llvm {
friend class ScalarEvolution; friend class ScalarEvolution;
SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
const SCEV *op, const Type *ty); const SCEV *op, Type *ty);
public: public:
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -119,7 +119,7 @@ namespace llvm {
friend class ScalarEvolution; friend class ScalarEvolution;
SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
const SCEV *op, const Type *ty); const SCEV *op, Type *ty);
public: public:
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -158,7 +158,7 @@ namespace llvm {
op_iterator op_begin() const { return Operands; } op_iterator op_begin() const { return Operands; }
op_iterator op_end() const { return Operands + NumOperands; } op_iterator op_end() const { return Operands + NumOperands; }
const Type *getType() const { return getOperand(0)->getType(); } Type *getType() const { return getOperand(0)->getType(); }
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const { NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const {
return (NoWrapFlags)(SubclassData & Mask); return (NoWrapFlags)(SubclassData & Mask);
@ -214,7 +214,7 @@ namespace llvm {
} }
public: public:
const Type *getType() const { Type *getType() const {
// Use the type of the last operand, which is likely to be a pointer // Use the type of the last operand, which is likely to be a pointer
// type, if there is one. This doesn't usually matter, but it can help // type, if there is one. This doesn't usually matter, but it can help
// reduce casts when the expressions are expanded. // reduce casts when the expressions are expanded.
@ -263,7 +263,7 @@ namespace llvm {
const SCEV *getLHS() const { return LHS; } const SCEV *getLHS() const { return LHS; }
const SCEV *getRHS() const { return RHS; } const SCEV *getRHS() const { return RHS; }
const Type *getType() const { Type *getType() const {
// In most cases the types of LHS and RHS will be the same, but in some // In most cases the types of LHS and RHS will be the same, but in some
// crazy cases one or the other may be a pointer. ScalarEvolution doesn't // crazy cases one or the other may be a pointer. ScalarEvolution doesn't
// depend on the type for correctness, but handling types carefully can // depend on the type for correctness, but handling types carefully can
@ -441,11 +441,11 @@ namespace llvm {
/// folded with other operations into something unrecognizable. This /// folded with other operations into something unrecognizable. This
/// is mainly only useful for pretty-printing and other situations /// is mainly only useful for pretty-printing and other situations
/// where it isn't absolutely required for these to succeed. /// where it isn't absolutely required for these to succeed.
bool isSizeOf(const Type *&AllocTy) const; bool isSizeOf(Type *&AllocTy) const;
bool isAlignOf(const Type *&AllocTy) const; bool isAlignOf(Type *&AllocTy) const;
bool isOffsetOf(const Type *&STy, Constant *&FieldNo) const; bool isOffsetOf(Type *&STy, Constant *&FieldNo) const;
const Type *getType() const { return getValPtr()->getType(); } Type *getType() const { return getValPtr()->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast: /// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SCEVUnknown *S) { return true; } static inline bool classof(const SCEVUnknown *S) { return true; }

View File

@ -39,7 +39,7 @@ class Argument : public Value, public ilist_node<Argument> {
/// Argument ctor - If Function argument is specified, this argument is /// Argument ctor - If Function argument is specified, this argument is
/// inserted at the end of the argument list for the function. /// inserted at the end of the argument list for the function.
/// ///
explicit Argument(const Type *Ty, const Twine &Name = "", Function *F = 0); explicit Argument(Type *Ty, const Twine &Name = "", Function *F = 0);
inline const Function *getParent() const { return Parent; } inline const Function *getParent() const { return Parent; }
inline Function *getParent() { return Parent; } inline Function *getParent() { return Parent; }

View File

@ -65,8 +65,7 @@ const Attributes StackAlignment = 7<<26; ///< Alignment of stack for
///of alignment with +1 bias ///of alignment with +1 bias
///0 means unaligned (different from ///0 means unaligned (different from
///alignstack(1)) ///alignstack(1))
const Attributes Hotpatch = 1<<29; ///< Function should have special const Attributes ReturnsTwice = 1<<29; ///< Function can return twice
///'hotpatch' sequence in prologue
const Attributes UWTable = 1<<30; ///< Function must be in a unwind const Attributes UWTable = 1<<30; ///< Function must be in a unwind
///table ///table
const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or
@ -93,7 +92,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment |
Hotpatch | UWTable | NonLazyBind; UWTable | NonLazyBind | ReturnsTwice;
/// @brief Parameter attributes that do not apply to vararg call arguments. /// @brief Parameter attributes that do not apply to vararg call arguments.
const Attributes VarArgsIncompatible = StructRet; const Attributes VarArgsIncompatible = StructRet;
@ -107,7 +106,7 @@ const Attributes MutuallyIncompatible[4] = {
}; };
/// @brief Which attributes cannot be applied to a type. /// @brief Which attributes cannot be applied to a type.
Attributes typeIncompatible(const Type *Ty); Attributes typeIncompatible(Type *Ty);
/// This turns an int alignment (a power of 2, normally) into the /// This turns an int alignment (a power of 2, normally) into the
/// form used internally in Attributes. /// form used internally in Attributes.

View File

@ -43,6 +43,10 @@ namespace llvm {
/// This function checks debug info intrinsics. If an intrinsic is invalid /// This function checks debug info intrinsics. If an intrinsic is invalid
/// then this function simply removes the intrinsic. /// then this function simply removes the intrinsic.
void CheckDebugInfoIntrinsics(Module *M); void CheckDebugInfoIntrinsics(Module *M);
/// This function upgrades the old pre-3.0 exception handling system to the
/// new one. N.B. This will be removed in 3.1.
void UpgradeExceptionHandling(Module *M);
} // End llvm namespace } // End llvm namespace
#endif #endif

View File

@ -22,6 +22,7 @@
namespace llvm { namespace llvm {
class LandingPadInst;
class TerminatorInst; class TerminatorInst;
class LLVMContext; class LLVMContext;
class BlockAddress; class BlockAddress;
@ -144,6 +145,14 @@ class BasicBlock : public Value, // Basic blocks are data objects also
return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime(); return const_cast<BasicBlock*>(this)->getFirstNonPHIOrDbgOrLifetime();
} }
/// getFirstInsertionPt - Returns an iterator to the first instruction in this
/// block that is suitable for inserting a non-PHI instruction. In particular,
/// it skips all PHIs and LandingPad instructions.
iterator getFirstInsertionPt();
const_iterator getFirstInsertionPt() const {
return const_cast<BasicBlock*>(this)->getFirstInsertionPt();
}
/// removeFromParent - This method unlinks 'this' from the containing /// removeFromParent - This method unlinks 'this' from the containing
/// function, but does not delete it. /// function, but does not delete it.
/// ///
@ -258,6 +267,14 @@ class BasicBlock : public Value, // Basic blocks are data objects also
/// to refer to basic block New instead of to us. /// to refer to basic block New instead of to us.
void replaceSuccessorsPhiUsesWith(BasicBlock *New); void replaceSuccessorsPhiUsesWith(BasicBlock *New);
/// isLandingPad - Return true if this basic block is a landing pad. I.e.,
/// it's the destination of the 'unwind' edge of an invoke instruction.
bool isLandingPad() const;
/// getLandingPadInst() - Return the landingpad instruction associated with
/// the landing pad.
LandingPadInst *getLandingPadInst();
private: private:
/// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress /// AdjustBlockAddressRefCount - BasicBlock stores the number of BlockAddress
/// objects using it. This is almost always 0, sometimes one, possibly but /// objects using it. This is almost always 0, sometimes one, possibly but

View File

@ -205,6 +205,23 @@ namespace bitc {
BINOP_XOR = 12 BINOP_XOR = 12
}; };
/// These are values used in the bitcode files to encode AtomicRMW operations.
/// The values of these enums have no fixed relation to the LLVM IR enum
/// values. Changing these will break compatibility with old files.
enum RMWOperations {
RMW_XCHG = 0,
RMW_ADD = 1,
RMW_SUB = 2,
RMW_AND = 3,
RMW_NAND = 4,
RMW_OR = 5,
RMW_XOR = 6,
RMW_MAX = 7,
RMW_MIN = 8,
RMW_UMAX = 9,
RMW_UMIN = 10
};
/// OverflowingBinaryOperatorOptionalFlags - Flags for serializing /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
/// OverflowingBinaryOperator's SubclassOptionalData contents. /// OverflowingBinaryOperator's SubclassOptionalData contents.
enum OverflowingBinaryOperatorOptionalFlags { enum OverflowingBinaryOperatorOptionalFlags {
@ -218,6 +235,23 @@ namespace bitc {
PEO_EXACT = 0 PEO_EXACT = 0
}; };
/// Encoded AtomicOrdering values.
enum AtomicOrderingCodes {
ORDERING_NOTATOMIC = 0,
ORDERING_UNORDERED = 1,
ORDERING_MONOTONIC = 2,
ORDERING_ACQUIRE = 3,
ORDERING_RELEASE = 4,
ORDERING_ACQREL = 5,
ORDERING_SEQCST = 6
};
/// Encoded SynchronizationScope values.
enum AtomicSynchScopeCodes {
SYNCHSCOPE_SINGLETHREAD = 0,
SYNCHSCOPE_CROSSTHREAD = 1
};
// The function body block (FUNCTION_BLOCK_ID) describes function bodies. It // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It
// can contain a constant block (CONSTANTS_BLOCK_ID). // can contain a constant block (CONSTANTS_BLOCK_ID).
enum FunctionCodes { enum FunctionCodes {
@ -266,7 +300,19 @@ namespace bitc {
FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...] FUNC_CODE_INST_CALL = 34, // CALL: [attr, fnty, fnid, args...]
FUNC_CODE_DEBUG_LOC = 35 // DEBUG_LOC: [Line,Col,ScopeVal, IAVal] FUNC_CODE_DEBUG_LOC = 35, // DEBUG_LOC: [Line,Col,ScopeVal, IAVal]
FUNC_CODE_INST_FENCE = 36, // FENCE: [ordering, synchscope]
FUNC_CODE_INST_CMPXCHG = 37, // CMPXCHG: [ptrty,ptr,cmp,new, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_ATOMICRMW = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
// align, vol,
// ordering, synchscope]
FUNC_CODE_INST_RESUME = 39, // RESUME: [opval]
FUNC_CODE_INST_LANDINGPAD = 40, // LANDINGPAD: [ty,val,val,num,id0,val0...]
FUNC_CODE_INST_LOADATOMIC = 41, // LOAD: [opty, op, align, vol,
// ordering, synchscope]
FUNC_CODE_INST_STOREATOMIC = 42 // STORE: [ptrty,ptr,val, align, vol
// ordering, synchscope]
}; };
} // End bitc namespace } // End bitc namespace
} // End llvm namespace } // End llvm namespace

View File

@ -33,12 +33,12 @@ class SelectionDAG;
/// of insertvalue or extractvalue indices that identify a member, return /// of insertvalue or extractvalue indices that identify a member, return
/// the linearized index of the start of the member. /// the linearized index of the start of the member.
/// ///
unsigned ComputeLinearIndex(const Type *Ty, unsigned ComputeLinearIndex(Type *Ty,
const unsigned *Indices, const unsigned *Indices,
const unsigned *IndicesEnd, const unsigned *IndicesEnd,
unsigned CurIndex = 0); unsigned CurIndex = 0);
inline unsigned ComputeLinearIndex(const Type *Ty, inline unsigned ComputeLinearIndex(Type *Ty,
ArrayRef<unsigned> Indices, ArrayRef<unsigned> Indices,
unsigned CurIndex = 0) { unsigned CurIndex = 0) {
return ComputeLinearIndex(Ty, Indices.begin(), Indices.end(), CurIndex); return ComputeLinearIndex(Ty, Indices.begin(), Indices.end(), CurIndex);
@ -51,7 +51,7 @@ inline unsigned ComputeLinearIndex(const Type *Ty,
/// If Offsets is non-null, it points to a vector to be filled in /// If Offsets is non-null, it points to a vector to be filled in
/// with the in-memory offsets of each of the individual values. /// with the in-memory offsets of each of the individual values.
/// ///
void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty, void ComputeValueVTs(const TargetLowering &TLI, Type *Ty,
SmallVectorImpl<EVT> &ValueVTs, SmallVectorImpl<EVT> &ValueVTs,
SmallVectorImpl<uint64_t> *Offsets = 0, SmallVectorImpl<uint64_t> *Offsets = 0,
uint64_t StartingOffset = 0); uint64_t StartingOffset = 0);

View File

@ -49,11 +49,6 @@ namespace llvm {
const MachineLoopInfo &loops) : const MachineLoopInfo &loops) :
MF(mf), LIS(lis), Loops(loops) {} MF(mf), LIS(lis), Loops(loops) {}
/// CalculateRegClass - recompute the register class for reg from its uses.
/// Since the register class can affect the allocation hint, this function
/// should be called before CalculateWeightAndHint if both are called.
void CalculateRegClass(unsigned reg);
/// CalculateWeightAndHint - (re)compute li's spill weight and allocation /// CalculateWeightAndHint - (re)compute li's spill weight and allocation
/// hint. /// hint.
void CalculateWeightAndHint(LiveInterval &li); void CalculateWeightAndHint(LiveInterval &li);

View File

@ -54,8 +54,18 @@ class FastISel {
const TargetInstrInfo &TII; const TargetInstrInfo &TII;
const TargetLowering &TLI; const TargetLowering &TLI;
const TargetRegisterInfo &TRI; const TargetRegisterInfo &TRI;
/// The position of the last instruction for materializing constants
/// for use in the current block. It resets to EmitStartPt when it
/// makes sense (for example, it's usually profitable to avoid function
/// calls between the definition and the use)
MachineInstr *LastLocalValue; MachineInstr *LastLocalValue;
/// The top most instruction in the current block that is allowed for
/// emitting local variables. LastLocalValue resets to EmitStartPt when
/// it makes sense (for example, on function calls)
MachineInstr *EmitStartPt;
public: public:
/// getLastLocalValue - Return the position of the last instruction /// getLastLocalValue - Return the position of the last instruction
/// emitted for materializing constants for use in the current block. /// emitted for materializing constants for use in the current block.
@ -63,7 +73,10 @@ class FastISel {
/// setLastLocalValue - Update the position of the last instruction /// setLastLocalValue - Update the position of the last instruction
/// emitted for materializing constants for use in the current block. /// emitted for materializing constants for use in the current block.
void setLastLocalValue(MachineInstr *I) { LastLocalValue = I; } void setLastLocalValue(MachineInstr *I) {
EmitStartPt = I;
LastLocalValue = I;
}
/// startNewBlock - Set the current block to which generated machine /// startNewBlock - Set the current block to which generated machine
/// instructions will be appended, and clear the local CSE map. /// instructions will be appended, and clear the local CSE map.
@ -358,6 +371,11 @@ class FastISel {
/// be materialized with new instructions. /// be materialized with new instructions.
unsigned materializeRegForValue(const Value *V, MVT VT); unsigned materializeRegForValue(const Value *V, MVT VT);
/// flushLocalValueMap - clears LocalValueMap and moves the area for the
/// new local variables to the beginning of the block. It helps to avoid
/// spilling cached variables across heavy instructions like calls.
void flushLocalValueMap();
/// hasTrivialKill - Test whether the given value has exactly one use. /// hasTrivialKill - Test whether the given value has exactly one use.
bool hasTrivialKill(const Value *V) const; bool hasTrivialKill(const Value *V) const;
}; };

View File

@ -19,6 +19,7 @@
#include "llvm/Instructions.h" #include "llvm/Instructions.h"
#include "llvm/ADT/APInt.h" #include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#ifndef NDEBUG #ifndef NDEBUG
@ -139,7 +140,7 @@ class FunctionLoweringInfo {
unsigned CreateReg(EVT VT); unsigned CreateReg(EVT VT);
unsigned CreateRegs(const Type *Ty); unsigned CreateRegs(Type *Ty);
unsigned InitializeRegForValue(const Value *V) { unsigned InitializeRegForValue(const Value *V) {
unsigned &R = ValueMap[V]; unsigned &R = ValueMap[V];
@ -198,12 +199,12 @@ class FunctionLoweringInfo {
LiveOutRegInfo[Reg].IsValid = false; LiveOutRegInfo[Reg].IsValid = false;
} }
/// setByValArgumentFrameIndex - Record frame index for the byval /// setArgumentFrameIndex - Record frame index for the byval
/// argument. /// argument.
void setByValArgumentFrameIndex(const Argument *A, int FI); void setArgumentFrameIndex(const Argument *A, int FI);
/// getByValArgumentFrameIndex - Get frame index for the byval argument. /// getArgumentFrameIndex - Get frame index for the byval argument.
int getByValArgumentFrameIndex(const Argument *A); int getArgumentFrameIndex(const Argument *A);
private: private:
/// LiveOutRegInfo - Information about live out vregs. /// LiveOutRegInfo - Information about live out vregs.
@ -220,6 +221,11 @@ void AddCatchInfo(const CallInst &I,
void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad, void CopyCatchInfo(const BasicBlock *SuccBB, const BasicBlock *LPad,
MachineModuleInfo *MMI, FunctionLoweringInfo &FLI); MachineModuleInfo *MMI, FunctionLoweringInfo &FLI);
/// AddLandingPadInfo - Extract the exception handling information from the
/// landingpad instruction and add them to the specified machine module info.
void AddLandingPadInfo(const LandingPadInst &I, MachineModuleInfo &MMI,
MachineBasicBlock *MBB);
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -95,7 +95,7 @@ namespace ISD {
// execution to HANDLER. Many platform-related details also :) // execution to HANDLER. Many platform-related details also :)
EH_RETURN, EH_RETURN,
// OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) // RESULT, OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer)
// This corresponds to the eh.sjlj.setjmp intrinsic. // This corresponds to the eh.sjlj.setjmp intrinsic.
// It takes an input chain and a pointer to the jump buffer as inputs // It takes an input chain and a pointer to the jump buffer as inputs
// and returns an outchain. // and returns an outchain.
@ -323,6 +323,12 @@ namespace ISD {
// i1 then the high bits must conform to getBooleanContents. // i1 then the high bits must conform to getBooleanContents.
SELECT, SELECT,
// Select with a vector condition (op #0) and two vector operands (ops #1
// and #2), returning a vector result. All vectors have the same length.
// Much like the scalar select and setcc, each bit in the condition selects
// whether the corresponding result element is taken from op #1 or op #2.
VSELECT,
// Select with condition operator - This selects between a true value and // Select with condition operator - This selects between a true value and
// a false value (ops #2 and #3) based on the boolean result of comparing // a false value (ops #2 and #3) based on the boolean result of comparing
// the lhs and rhs (ops #0 and #1) of a conditional expression with the // the lhs and rhs (ops #0 and #1) of a conditional expression with the
@ -333,16 +339,10 @@ namespace ISD {
// true. If the result value type is not i1 then the high bits conform // true. If the result value type is not i1 then the high bits conform
// to getBooleanContents. The operands to this are the left and right // to getBooleanContents. The operands to this are the left and right
// operands to compare (ops #0, and #1) and the condition code to compare // operands to compare (ops #0, and #1) and the condition code to compare
// them with (op #2) as a CondCodeSDNode. // them with (op #2) as a CondCodeSDNode. If the operands are vector types
// then the result type must also be a vector type.
SETCC, SETCC,
// RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of
// integer elements with all bits of the result elements set to true if the
// comparison is true or all cleared if the comparison is false. The
// operands to this are the left and right operands to compare (LHS/RHS) and
// the condition code to compare them with (COND) as a CondCodeSDNode.
VSETCC,
// SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
// integer shift operations, just like ADD/SUB_PARTS. The operation // integer shift operations, just like ADD/SUB_PARTS. The operation
// ordering is: // ordering is:
@ -566,14 +566,19 @@ namespace ISD {
// HANDLENODE node - Used as a handle for various purposes. // HANDLENODE node - Used as a handle for various purposes.
HANDLENODE, HANDLENODE,
// TRAMPOLINE - This corresponds to the init_trampoline intrinsic. // INIT_TRAMPOLINE - This corresponds to the init_trampoline intrinsic. It
// It takes as input a token chain, the pointer to the trampoline, // takes as input a token chain, the pointer to the trampoline, the pointer
// the pointer to the nested function, the pointer to pass for the // to the nested function, the pointer to pass for the 'nest' parameter, a
// 'nest' parameter, a SRCVALUE for the trampoline and another for // SRCVALUE for the trampoline and another for the nested function (allowing
// the nested function (allowing targets to access the original // targets to access the original Function*). It produces a token chain as
// Function*). It produces the result of the intrinsic and a token // output.
// chain as output. INIT_TRAMPOLINE,
TRAMPOLINE,
// ADJUST_TRAMPOLINE - This corresponds to the adjust_trampoline intrinsic.
// It takes a pointer to the trampoline and produces a (possibly) new
// pointer to the same trampoline with platform-specific adjustments
// applied. The pointer it returns points to an executable block of code.
ADJUST_TRAMPOLINE,
// TRAP - Trapping instruction // TRAP - Trapping instruction
TRAP, TRAP,
@ -592,22 +597,27 @@ namespace ISD {
// and produces an output chain. // and produces an output chain.
MEMBARRIER, MEMBARRIER,
// OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope)
// This corresponds to the fence instruction. It takes an input chain, and
// two integer constants: an AtomicOrdering and a SynchronizationScope.
ATOMIC_FENCE,
// Val, OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr)
// This corresponds to "load atomic" instruction.
ATOMIC_LOAD,
// OUTCHAIN = ATOMIC_LOAD(INCHAIN, ptr, val)
// This corresponds to "store atomic" instruction.
ATOMIC_STORE,
// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap) // Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap)
// this corresponds to the atomic.lcs intrinsic. // This corresponds to the cmpxchg instruction.
// cmp is compared to *ptr, and if equal, swap is stored in *ptr.
// the return is always the original value in *ptr
ATOMIC_CMP_SWAP, ATOMIC_CMP_SWAP,
// Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt) // Val, OUTCHAIN = ATOMIC_SWAP(INCHAIN, ptr, amt)
// this corresponds to the atomic.swap intrinsic.
// amt is stored to *ptr atomically.
// the return is always the original value in *ptr
ATOMIC_SWAP,
// Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt) // Val, OUTCHAIN = ATOMIC_LOAD_[OpName](INCHAIN, ptr, amt)
// this corresponds to the atomic.load.[OpName] intrinsic. // These correspond to the atomicrmw instruction.
// op(*ptr, amt) is stored to *ptr atomically. ATOMIC_SWAP,
// the return is always the original value in *ptr
ATOMIC_LOAD_ADD, ATOMIC_LOAD_ADD,
ATOMIC_LOAD_SUB, ATOMIC_LOAD_SUB,
ATOMIC_LOAD_AND, ATOMIC_LOAD_AND,

View File

@ -0,0 +1,248 @@
//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements LexicalScopes analysis.
//
// This pass collects lexical scope information and maps machine instructions
// to respective lexical scopes.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_LEXICALSCOPES_H
#define LLVM_CODEGEN_LEXICALSCOPES_H
#include "llvm/Metadata.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/ValueHandle.h"
#include <utility>
namespace llvm {
class MachineInstr;
class MachineBasicBlock;
class MachineFunction;
class LexicalScope;
//===----------------------------------------------------------------------===//
/// InsnRange - This is used to track range of instructions with identical
/// lexical scope.
///
typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange;
//===----------------------------------------------------------------------===//
/// LexicalScopes - This class provides interface to collect and use lexical
/// scoping information from machine instruction.
///
class LexicalScopes {
public:
LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) { }
virtual ~LexicalScopes();
/// initialize - Scan machine function and constuct lexical scope nest.
virtual void initialize(const MachineFunction &);
/// releaseMemory - release memory.
virtual void releaseMemory();
/// empty - Return true if there is any lexical scope information available.
bool empty() { return CurrentFnLexicalScope == NULL; }
/// isCurrentFunctionScope - Return true if given lexical scope represents
/// current function.
bool isCurrentFunctionScope(const LexicalScope *LS) {
return LS == CurrentFnLexicalScope;
}
/// getCurrentFunctionScope - Return lexical scope for the current function.
LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope;}
/// getMachineBasicBlocks - Populate given set using machine basic blocks
/// which have machine instructions that belong to lexical scope identified by
/// DebugLoc.
void getMachineBasicBlocks(DebugLoc DL,
SmallPtrSet<const MachineBasicBlock*, 4> &MBBs);
/// dominates - Return true if DebugLoc's lexical scope dominates at least one
/// machine instruction's lexical scope in a given machine basic block.
bool dominates(DebugLoc DL, MachineBasicBlock *MBB);
/// findLexicalScope - Find lexical scope, either regular or inlined, for the
/// given DebugLoc. Return NULL if not found.
LexicalScope *findLexicalScope(DebugLoc DL);
/// getAbstractScopesList - Return a reference to list of abstract scopes.
ArrayRef<LexicalScope *> getAbstractScopesList() const {
return AbstractScopesList;
}
/// findAbstractScope - Find an abstract scope or return NULL.
LexicalScope *findAbstractScope(const MDNode *N) {
return AbstractScopeMap.lookup(N);
}
/// findInlinedScope - Find an inlined scope for the given DebugLoc or return
/// NULL.
LexicalScope *findInlinedScope(DebugLoc DL) {
return InlinedLexicalScopeMap.lookup(DL);
}
/// findLexicalScope - Find regular lexical scope or return NULL.
LexicalScope *findLexicalScope(const MDNode *N) {
return LexicalScopeMap.lookup(N);
}
/// dump - Print data structures to dbgs().
void dump();
private:
/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If
/// not available then create new lexical scope.
LexicalScope *getOrCreateLexicalScope(DebugLoc DL);
/// getOrCreateRegularScope - Find or create a regular lexical scope.
LexicalScope *getOrCreateRegularScope(MDNode *Scope);
/// getOrCreateInlinedScope - Find or create an inlined lexical scope.
LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt);
/// getOrCreateAbstractScope - Find or create an abstract lexical scope.
LexicalScope *getOrCreateAbstractScope(const MDNode *N);
/// extractLexicalScopes - Extract instruction ranges for each lexical scopes
/// for the given machine function.
void extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges,
DenseMap<const MachineInstr *, LexicalScope *> &M);
void constructScopeNest(LexicalScope *Scope);
void assignInstructionRanges(SmallVectorImpl<InsnRange> &MIRanges,
DenseMap<const MachineInstr *, LexicalScope *> &M);
private:
const MachineFunction *MF;
/// LexicalScopeMap - Tracks the scopes in the current function. Owns the
/// contained LexicalScope*s.
DenseMap<const MDNode *, LexicalScope *> LexicalScopeMap;
/// InlinedLexicalScopeMap - Tracks inlined function scopes in current function.
DenseMap<DebugLoc, LexicalScope *> InlinedLexicalScopeMap;
/// AbstractScopeMap - These scopes are not included LexicalScopeMap.
/// AbstractScopes owns its LexicalScope*s.
DenseMap<const MDNode *, LexicalScope *> AbstractScopeMap;
/// AbstractScopesList - Tracks abstract scopes constructed while processing
/// a function.
SmallVector<LexicalScope *, 4>AbstractScopesList;
/// CurrentFnLexicalScope - Top level scope for the current function.
///
LexicalScope *CurrentFnLexicalScope;
};
//===----------------------------------------------------------------------===//
/// LexicalScope - This class is used to track scope information.
///
class LexicalScope {
public:
LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A)
: Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A),
LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0), IndentLevel(0) {
if (Parent)
Parent->addChild(this);
}
virtual ~LexicalScope() {}
// Accessors.
LexicalScope *getParent() const { return Parent; }
const MDNode *getDesc() const { return Desc; }
const MDNode *getInlinedAt() const { return InlinedAtLocation; }
const MDNode *getScopeNode() const { return Desc; }
bool isAbstractScope() const { return AbstractScope; }
SmallVector<LexicalScope *, 4> &getChildren() { return Children; }
SmallVector<InsnRange, 4> &getRanges() { return Ranges; }
/// addChild - Add a child scope.
void addChild(LexicalScope *S) { Children.push_back(S); }
/// openInsnRange - This scope covers instruction range starting from MI.
void openInsnRange(const MachineInstr *MI) {
if (!FirstInsn)
FirstInsn = MI;
if (Parent)
Parent->openInsnRange(MI);
}
/// extendInsnRange - Extend the current instruction range covered by
/// this scope.
void extendInsnRange(const MachineInstr *MI) {
assert (FirstInsn && "MI Range is not open!");
LastInsn = MI;
if (Parent)
Parent->extendInsnRange(MI);
}
/// closeInsnRange - Create a range based on FirstInsn and LastInsn collected
/// until now. This is used when a new scope is encountered while walking
/// machine instructions.
void closeInsnRange(LexicalScope *NewScope = NULL) {
assert (LastInsn && "Last insn missing!");
Ranges.push_back(InsnRange(FirstInsn, LastInsn));
FirstInsn = NULL;
LastInsn = NULL;
// If Parent dominates NewScope then do not close Parent's instruction
// range.
if (Parent && (!NewScope || !Parent->dominates(NewScope)))
Parent->closeInsnRange(NewScope);
}
/// dominates - Return true if current scope dominsates given lexical scope.
bool dominates(const LexicalScope *S) const {
if (S == this)
return true;
if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut())
return true;
return false;
}
// Depth First Search support to walk and manipulate LexicalScope hierarchy.
unsigned getDFSOut() const { return DFSOut; }
void setDFSOut(unsigned O) { DFSOut = O; }
unsigned getDFSIn() const { return DFSIn; }
void setDFSIn(unsigned I) { DFSIn = I; }
/// dump - print lexical scope.
void dump() const;
private:
LexicalScope *Parent; // Parent to this scope.
AssertingVH<const MDNode> Desc; // Debug info descriptor.
AssertingVH<const MDNode> InlinedAtLocation; // Location at which this
// scope is inlined.
bool AbstractScope; // Abstract Scope
SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope.
// Contents not owned.
SmallVector<InsnRange, 4> Ranges;
const MachineInstr *LastInsn; // Last instruction of this scope.
const MachineInstr *FirstInsn; // First instruction of this scope.
unsigned DFSIn, DFSOut; // In & Out Depth use to determine
// scope nesting.
mutable unsigned IndentLevel; // Private state for dump()
};
} // end llvm namespace
#endif

View File

@ -100,6 +100,7 @@ namespace llvm {
bool isDefByCopy() const { return copy != 0; } bool isDefByCopy() const { return copy != 0; }
/// Returns true if one or more kills are PHI nodes. /// Returns true if one or more kills are PHI nodes.
/// Obsolete, do not use!
bool hasPHIKill() const { return flags & HAS_PHI_KILL; } bool hasPHIKill() const { return flags & HAS_PHI_KILL; }
/// Set the PHI kill flag on this value. /// Set the PHI kill flag on this value.
void setHasPHIKill(bool hasKill) { void setHasPHIKill(bool hasKill) {
@ -313,7 +314,6 @@ namespace llvm {
/// RenumberValues - Renumber all values in order of appearance and remove /// RenumberValues - Renumber all values in order of appearance and remove
/// unused values. /// unused values.
/// Recalculate phi-kill flags in case any phi-def values were removed.
void RenumberValues(LiveIntervals &lis); void RenumberValues(LiveIntervals &lis);
/// isOnlyLROfValNo - Return true if the specified live range is the only /// isOnlyLROfValNo - Return true if the specified live range is the only
@ -411,6 +411,14 @@ namespace llvm {
return I == end() ? 0 : I->valno; return I == end() ? 0 : I->valno;
} }
/// getVNInfoBefore - Return the VNInfo that is live up to but not
/// necessarilly including Idx, or NULL. Use this to find the reaching def
/// used by an instruction at this SlotIndex position.
VNInfo *getVNInfoBefore(SlotIndex Idx) const {
const_iterator I = FindLiveRangeContaining(Idx.getPrevSlot());
return I == end() ? 0 : I->valno;
}
/// FindLiveRangeContaining - Return an iterator to the live range that /// FindLiveRangeContaining - Return an iterator to the live range that
/// contains the specified index, or end() if there is none. /// contains the specified index, or end() if there is none.
iterator FindLiveRangeContaining(SlotIndex Idx) { iterator FindLiveRangeContaining(SlotIndex Idx) {
@ -452,10 +460,10 @@ namespace llvm {
addRangeFrom(LR, ranges.begin()); addRangeFrom(LR, ranges.begin());
} }
/// extendInBlock - If this interval is live before UseIdx in the basic /// extendInBlock - If this interval is live before Kill in the basic block
/// block that starts at StartIdx, extend it to be live at UseIdx and return /// that starts at StartIdx, extend it to be live up to Kill, and return
/// the value. If there is no live range before UseIdx, return NULL. /// the value. If there is no live range before Kill, return NULL.
VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex UseIdx); VNInfo *extendInBlock(SlotIndex StartIdx, SlotIndex Kill);
/// join - Join two live intervals (this, and other) together. This applies /// join - Join two live intervals (this, and other) together. This applies
/// mappings to the value numbers in the LHS/RHS intervals as specified. If /// mappings to the value numbers in the LHS/RHS intervals as specified. If

View File

@ -25,6 +25,8 @@
namespace llvm { namespace llvm {
class LiveStacks : public MachineFunctionPass { class LiveStacks : public MachineFunctionPass {
const TargetRegisterInfo *TRI;
/// Special pool allocator for VNInfo's (LiveInterval val#). /// Special pool allocator for VNInfo's (LiveInterval val#).
/// ///
VNInfo::Allocator VNInfoAllocator; VNInfo::Allocator VNInfoAllocator;

View File

@ -231,6 +231,7 @@ class LiveVariables : public MachineFunctionPass {
} }
assert(Removed && "Register is not used by this instruction!"); assert(Removed && "Register is not used by this instruction!");
(void)Removed;
return true; return true;
} }
@ -265,6 +266,7 @@ class LiveVariables : public MachineFunctionPass {
} }
} }
assert(Removed && "Register is not defined by this instruction!"); assert(Removed && "Register is not defined by this instruction!");
(void)Removed;
return true; return true;
} }

View File

@ -232,7 +232,7 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
/// setIsLandingPad - Indicates the block is a landing pad. That is /// setIsLandingPad - Indicates the block is a landing pad. That is
/// this basic block is entered via an exception handler. /// this basic block is entered via an exception handler.
void setIsLandingPad() { IsLandingPad = true; } void setIsLandingPad(bool V = true) { IsLandingPad = V; }
/// getLandingPadSuccessor - If this block has a successor that is a landing /// getLandingPadSuccessor - If this block has a successor that is a landing
/// pad, return it. Otherwise return NULL. /// pad, return it. Otherwise return NULL.

View File

@ -1,4 +1,4 @@
//====----- MachineBlockFrequency.h - MachineBlock Frequency Analysis ----====// //====----- MachineBlockFrequencyInfo.h - MachineBlock Frequency Analysis ----====//
// //
// The LLVM Compiler Infrastructure // The LLVM Compiler Infrastructure
// //
@ -11,10 +11,11 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H #ifndef LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
#define LLVM_CODEGEN_MACHINEBLOCKFREQUENCY_H #define LLVM_CODEGEN_MACHINEBLOCKFREQUENCYINFO_H
#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/Support/BlockFrequency.h"
#include <climits> #include <climits>
namespace llvm { namespace llvm {
@ -23,29 +24,29 @@ class MachineBranchProbabilityInfo;
template<class BlockT, class FunctionT, class BranchProbInfoT> template<class BlockT, class FunctionT, class BranchProbInfoT>
class BlockFrequencyImpl; class BlockFrequencyImpl;
/// MachineBlockFrequency pass uses BlockFrequencyImpl implementation to estimate /// MachineBlockFrequencyInfo pass uses BlockFrequencyImpl implementation to estimate
/// machine basic block frequencies. /// machine basic block frequencies.
class MachineBlockFrequency : public MachineFunctionPass { class MachineBlockFrequencyInfo : public MachineFunctionPass {
BlockFrequencyImpl<MachineBasicBlock, MachineFunction, MachineBranchProbabilityInfo> *MBFI; BlockFrequencyImpl<MachineBasicBlock, MachineFunction, MachineBranchProbabilityInfo> *MBFI;
public: public:
static char ID; static char ID;
MachineBlockFrequency(); MachineBlockFrequencyInfo();
~MachineBlockFrequency(); ~MachineBlockFrequencyInfo();
void getAnalysisUsage(AnalysisUsage &AU) const; void getAnalysisUsage(AnalysisUsage &AU) const;
bool runOnMachineFunction(MachineFunction &F); bool runOnMachineFunction(MachineFunction &F);
/// getblockFreq - Return block frequency. Never return 0, value must be /// getblockFreq - Return block frequency. Return 0 if we don't have the
/// positive. Please note that initial frequency is equal to 1024. It means /// information. Please note that initial frequency is equal to 1024. It means
/// that we should not rely on the value itself, but only on the comparison to /// that we should not rely on the value itself, but only on the comparison to
/// the other block frequencies. We do this to avoid using of the floating /// the other block frequencies. We do this to avoid using of floating points.
/// points. ///
uint32_t getBlockFreq(MachineBasicBlock *MBB); BlockFrequency getBlockFreq(MachineBasicBlock *MBB) const;
}; };
} }

View File

@ -34,15 +34,15 @@ class raw_ostream;
/// Abstract base class for all machine specific constantpool value subclasses. /// Abstract base class for all machine specific constantpool value subclasses.
/// ///
class MachineConstantPoolValue { class MachineConstantPoolValue {
const Type *Ty; Type *Ty;
public: public:
explicit MachineConstantPoolValue(const Type *ty) : Ty(ty) {} explicit MachineConstantPoolValue(Type *ty) : Ty(ty) {}
virtual ~MachineConstantPoolValue() {} virtual ~MachineConstantPoolValue() {}
/// getType - get type of this MachineConstantPoolValue. /// getType - get type of this MachineConstantPoolValue.
/// ///
const Type *getType() const { return Ty; } Type *getType() const { return Ty; }
/// getRelocationInfo - This method classifies the entry according to /// getRelocationInfo - This method classifies the entry according to
@ -54,7 +54,7 @@ class MachineConstantPoolValue {
virtual int getExistingMachineCPValue(MachineConstantPool *CP, virtual int getExistingMachineCPValue(MachineConstantPool *CP,
unsigned Alignment) = 0; unsigned Alignment) = 0;
virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) = 0;
/// print - Implement operator<< /// print - Implement operator<<
virtual void print(raw_ostream &O) const = 0; virtual void print(raw_ostream &O) const = 0;
@ -104,7 +104,7 @@ class MachineConstantPoolEntry {
return Alignment & ~(1 << (sizeof(unsigned)*CHAR_BIT-1)); return Alignment & ~(1 << (sizeof(unsigned)*CHAR_BIT-1));
} }
const Type *getType() const; Type *getType() const;
/// getRelocationInfo - This method classifies the entry according to /// getRelocationInfo - This method classifies the entry according to
/// whether or not it may generate a relocation entry. This must be /// whether or not it may generate a relocation entry. This must be

View File

@ -174,6 +174,10 @@ class MachineFrameInfo {
/// StackProtectorIdx - The frame index for the stack protector. /// StackProtectorIdx - The frame index for the stack protector.
int StackProtectorIdx; int StackProtectorIdx;
/// FunctionContextIdx - The frame index for the function context. Used for
/// SjLj exceptions.
int FunctionContextIdx;
/// MaxCallFrameSize - This contains the size of the largest call frame if the /// MaxCallFrameSize - This contains the size of the largest call frame if the
/// target uses frame setup/destroy pseudo instructions (as defined in the /// target uses frame setup/destroy pseudo instructions (as defined in the
/// TargetFrameInfo class). This information is important for frame pointer /// TargetFrameInfo class). This information is important for frame pointer
@ -220,6 +224,7 @@ class MachineFrameInfo {
AdjustsStack = false; AdjustsStack = false;
HasCalls = false; HasCalls = false;
StackProtectorIdx = -1; StackProtectorIdx = -1;
FunctionContextIdx = -1;
MaxCallFrameSize = 0; MaxCallFrameSize = 0;
CSIValid = false; CSIValid = false;
LocalFrameSize = 0; LocalFrameSize = 0;
@ -244,6 +249,11 @@ class MachineFrameInfo {
int getStackProtectorIndex() const { return StackProtectorIdx; } int getStackProtectorIndex() const { return StackProtectorIdx; }
void setStackProtectorIndex(int I) { StackProtectorIdx = I; } void setStackProtectorIndex(int I) { StackProtectorIdx = I; }
/// getFunctionContextIndex/setFunctionContextIndex - Return the index for the
/// function context object. This object is used for SjLj exceptions.
int getFunctionContextIndex() const { return FunctionContextIdx; }
void setFunctionContextIndex(int I) { FunctionContextIdx = I; }
/// isFrameAddressTaken - This method may be called any time after instruction /// isFrameAddressTaken - This method may be called any time after instruction
/// selection is complete to determine if there is a call to /// selection is complete to determine if there is a call to
/// \@llvm.frameaddress in this function. /// \@llvm.frameaddress in this function.

View File

@ -32,6 +32,7 @@ namespace llvm {
template <typename T> class SmallVectorImpl; template <typename T> class SmallVectorImpl;
class AliasAnalysis; class AliasAnalysis;
class TargetInstrInfo; class TargetInstrInfo;
class TargetRegisterClass;
class TargetRegisterInfo; class TargetRegisterInfo;
class MachineFunction; class MachineFunction;
class MachineMemOperand; class MachineMemOperand;
@ -58,8 +59,6 @@ class MachineInstr : public ilist_node<MachineInstr> {
}; };
private: private:
const MCInstrDesc *MCID; // Instruction descriptor. const MCInstrDesc *MCID; // Instruction descriptor.
uint16_t NumImplicitOps; // Number of implicit operands (which
// are determined at construction time).
uint8_t Flags; // Various bits of additional uint8_t Flags; // Various bits of additional
// information about machine // information about machine
@ -78,9 +77,6 @@ class MachineInstr : public ilist_node<MachineInstr> {
MachineBasicBlock *Parent; // Pointer to the owning basic block. MachineBasicBlock *Parent; // Pointer to the owning basic block.
DebugLoc debugLoc; // Source line information. DebugLoc debugLoc; // Source line information.
// OperandComplete - Return true if it's illegal to add a new operand
bool OperandsComplete() const;
MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT
void operator=(const MachineInstr&); // DO NOT IMPLEMENT void operator=(const MachineInstr&); // DO NOT IMPLEMENT
@ -393,6 +389,30 @@ class MachineInstr : public ilist_node<MachineInstr> {
/// none is found. /// none is found.
int findFirstPredOperandIdx() const; int findFirstPredOperandIdx() const;
/// findInlineAsmFlagIdx() - Find the index of the flag word operand that
/// corresponds to operand OpIdx on an inline asm instruction. Returns -1 if
/// getOperand(OpIdx) does not belong to an inline asm operand group.
///
/// If GroupNo is not NULL, it will receive the number of the operand group
/// containing OpIdx.
///
/// The flag operand is an immediate that can be decoded with methods like
/// InlineAsm::hasRegClassConstraint().
///
int findInlineAsmFlagIdx(unsigned OpIdx, unsigned *GroupNo = 0) const;
/// getRegClassConstraint - Compute the static register class constraint for
/// operand OpIdx. For normal instructions, this is derived from the
/// MCInstrDesc. For inline assembly it is derived from the flag words.
///
/// Returns NULL if the static register classs constraint cannot be
/// determined.
///
const TargetRegisterClass*
getRegClassConstraint(unsigned OpIdx,
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) const;
/// isRegTiedToUseOperand - Given the index of a register def operand, /// isRegTiedToUseOperand - Given the index of a register def operand,
/// check if the register def is tied to a source operand, due to either /// check if the register def is tied to a source operand, due to either
/// two-address elimination or inline assembly constraints. Returns the /// two-address elimination or inline assembly constraints. Returns the

View File

@ -34,7 +34,7 @@
#include "llvm/Pass.h" #include "llvm/Pass.h"
#include "llvm/GlobalValue.h" #include "llvm/GlobalValue.h"
#include "llvm/Metadata.h" #include "llvm/Metadata.h"
#include "llvm/CodeGen/MachineLocation.h" #include "llvm/MC/MachineLocation.h"
#include "llvm/MC/MCContext.h" #include "llvm/MC/MCContext.h"
#include "llvm/Support/Dwarf.h" #include "llvm/Support/Dwarf.h"
#include "llvm/Support/DebugLoc.h" #include "llvm/Support/DebugLoc.h"
@ -107,36 +107,42 @@ class MachineModuleInfo : public ImmutablePass {
/// want. /// want.
MachineModuleInfoImpl *ObjFileMMI; MachineModuleInfoImpl *ObjFileMMI;
// FrameMoves - List of moves done by a function's prolog. Used to construct /// FrameMoves - List of moves done by a function's prolog. Used to construct
// frame maps by debug and exception handling consumers. /// frame maps by debug and exception handling consumers.
std::vector<MachineMove> FrameMoves; std::vector<MachineMove> FrameMoves;
// LandingPads - List of LandingPadInfo describing the landing pad information /// CompactUnwindEncoding - If the target supports it, this is the compact
// in the current function. /// unwind encoding. It replaces a function's CIE and FDE.
uint32_t CompactUnwindEncoding;
/// LandingPads - List of LandingPadInfo describing the landing pad
/// information in the current function.
std::vector<LandingPadInfo> LandingPads; std::vector<LandingPadInfo> LandingPads;
// Map of invoke call site index values to associated begin EH_LABEL for /// LPadToCallSiteMap - Map a landing pad's EH symbol to the call site
// the current function. /// indexes.
DenseMap<MCSymbol*, SmallVector<unsigned, 4> > LPadToCallSiteMap;
/// CallSiteMap - Map of invoke call site index values to associated begin
/// EH_LABEL for the current function.
DenseMap<MCSymbol*, unsigned> CallSiteMap; DenseMap<MCSymbol*, unsigned> CallSiteMap;
// The current call site index being processed, if any. 0 if none. /// CurCallSite - The current call site index being processed, if any. 0 if
/// none.
unsigned CurCallSite; unsigned CurCallSite;
// TypeInfos - List of C++ TypeInfo used in the current function. /// TypeInfos - List of C++ TypeInfo used in the current function.
//
std::vector<const GlobalVariable *> TypeInfos; std::vector<const GlobalVariable *> TypeInfos;
// FilterIds - List of typeids encoding filters used in the current function. /// FilterIds - List of typeids encoding filters used in the current function.
//
std::vector<unsigned> FilterIds; std::vector<unsigned> FilterIds;
// FilterEnds - List of the indices in FilterIds corresponding to filter /// FilterEnds - List of the indices in FilterIds corresponding to filter
// terminators. /// terminators.
//
std::vector<unsigned> FilterEnds; std::vector<unsigned> FilterEnds;
// Personalities - Vector of all personality functions ever seen. Used to emit /// Personalities - Vector of all personality functions ever seen. Used to
// common EH frames. /// emit common EH frames.
std::vector<const Function *> Personalities; std::vector<const Function *> Personalities;
/// UsedFunctions - The functions in the @llvm.used list in a more easily /// UsedFunctions - The functions in the @llvm.used list in a more easily
@ -144,7 +150,6 @@ class MachineModuleInfo : public ImmutablePass {
/// llvm.compiler.used. /// llvm.compiler.used.
SmallPtrSet<const Function *, 32> UsedFunctions; SmallPtrSet<const Function *, 32> UsedFunctions;
/// AddrLabelSymbols - This map keeps track of which symbol is being used for /// AddrLabelSymbols - This map keeps track of which symbol is being used for
/// the specified basic block's address of label. /// the specified basic block's address of label.
MMIAddrLabelMap *AddrLabelSymbols; MMIAddrLabelMap *AddrLabelSymbols;
@ -156,8 +161,9 @@ class MachineModuleInfo : public ImmutablePass {
/// in this module. /// in this module.
bool DbgInfoAvailable; bool DbgInfoAvailable;
/// True if this module calls VarArg function with floating point arguments. /// CallsExternalVAFunctionWithFloatingPointArguments - True if this module
/// This is used to emit an undefined reference to fltused on Windows targets. /// calls VarArg function with floating point arguments. This is used to emit
/// an undefined reference to fltused on Windows targets.
bool CallsExternalVAFunctionWithFloatingPointArguments; bool CallsExternalVAFunctionWithFloatingPointArguments;
public: public:
@ -170,7 +176,8 @@ class MachineModuleInfo : public ImmutablePass {
MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL. MachineModuleInfo(); // DUMMY CONSTRUCTOR, DO NOT CALL.
// Real constructor. // Real constructor.
MachineModuleInfo(const MCAsmInfo &MAI, const TargetAsmInfo *TAI); MachineModuleInfo(const MCAsmInfo &MAI, const MCRegisterInfo &MRI,
const MCObjectFileInfo *MOFI);
~MachineModuleInfo(); ~MachineModuleInfo();
bool doInitialization(); bool doInitialization();
@ -229,6 +236,15 @@ class MachineModuleInfo : public ImmutablePass {
/// handling comsumers. /// handling comsumers.
std::vector<MachineMove> &getFrameMoves() { return FrameMoves; } std::vector<MachineMove> &getFrameMoves() { return FrameMoves; }
/// getCompactUnwindEncoding - Returns the compact unwind encoding for a
/// function if the target supports the encoding. This encoding replaces a
/// function's CIE and FDE.
uint32_t getCompactUnwindEncoding() const { return CompactUnwindEncoding; }
/// setCompactUnwindEncoding - Set the compact unwind encoding for a function
/// if the target supports the encoding.
void setCompactUnwindEncoding(uint32_t Enc) { CompactUnwindEncoding = Enc; }
/// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// getAddrLabelSymbol - Return the symbol to be used for the specified basic
/// block when its address is taken. This cannot be its normal LBB label /// block when its address is taken. This cannot be its normal LBB label
/// because the block may be accessed outside its containing function. /// because the block may be accessed outside its containing function.
@ -286,12 +302,12 @@ class MachineModuleInfo : public ImmutablePass {
/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
/// ///
void addCatchTypeInfo(MachineBasicBlock *LandingPad, void addCatchTypeInfo(MachineBasicBlock *LandingPad,
std::vector<const GlobalVariable *> &TyInfo); ArrayRef<const GlobalVariable *> TyInfo);
/// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad.
/// ///
void addFilterTypeInfo(MachineBasicBlock *LandingPad, void addFilterTypeInfo(MachineBasicBlock *LandingPad,
std::vector<const GlobalVariable *> &TyInfo); ArrayRef<const GlobalVariable *> TyInfo);
/// addCleanup - Add a cleanup action for a landing pad. /// addCleanup - Add a cleanup action for a landing pad.
/// ///
@ -315,18 +331,42 @@ class MachineModuleInfo : public ImmutablePass {
return LandingPads; return LandingPads;
} }
/// setCallSiteBeginLabel - Map the begin label for a call site /// setCallSiteLandingPad - Map the landing pad's EH symbol to the call
/// site indexes.
void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef<unsigned> Sites);
/// getCallSiteLandingPad - Get the call site indexes for a landing pad EH
/// symbol.
SmallVectorImpl<unsigned> &getCallSiteLandingPad(MCSymbol *Sym) {
assert(hasCallSiteLandingPad(Sym) &&
"missing call site number for landing pad!");
return LPadToCallSiteMap[Sym];
}
/// hasCallSiteLandingPad - Return true if the landing pad Eh symbol has an
/// associated call site.
bool hasCallSiteLandingPad(MCSymbol *Sym) {
return !LPadToCallSiteMap[Sym].empty();
}
/// setCallSiteBeginLabel - Map the begin label for a call site.
void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) { void setCallSiteBeginLabel(MCSymbol *BeginLabel, unsigned Site) {
CallSiteMap[BeginLabel] = Site; CallSiteMap[BeginLabel] = Site;
} }
/// getCallSiteBeginLabel - Get the call site number for a begin label /// getCallSiteBeginLabel - Get the call site number for a begin label.
unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) { unsigned getCallSiteBeginLabel(MCSymbol *BeginLabel) {
assert(CallSiteMap.count(BeginLabel) && assert(hasCallSiteBeginLabel(BeginLabel) &&
"Missing call site number for EH_LABEL!"); "Missing call site number for EH_LABEL!");
return CallSiteMap[BeginLabel]; return CallSiteMap[BeginLabel];
} }
/// hasCallSiteBeginLabel - Return true if the begin label has a call site
/// number associated with it.
bool hasCallSiteBeginLabel(MCSymbol *BeginLabel) {
return CallSiteMap[BeginLabel] != 0;
}
/// setCurrentCallSite - Set the call site currently being processed. /// setCurrentCallSite - Set the call site currently being processed.
void setCurrentCallSite(unsigned Site) { CurCallSite = Site; } void setCurrentCallSite(unsigned Site) { CurCallSite = Site; }

View File

@ -83,8 +83,23 @@ class MachineOperand {
/// This is only valid on definitions of registers. /// This is only valid on definitions of registers.
bool IsDead : 1; bool IsDead : 1;
/// IsUndef - True if this is a register def / use of "undef", i.e. register /// IsUndef - True if this register operand reads an "undef" value, i.e. the
/// defined by an IMPLICIT_DEF. This is only valid on registers. /// read value doesn't matter. This flag can be set on both use and def
/// operands. On a sub-register def operand, it refers to the part of the
/// register that isn't written. On a full-register def operand, it is a
/// noop. See readsReg().
///
/// This is only valid on registers.
///
/// Note that an instruction may have multiple <undef> operands referring to
/// the same register. In that case, the instruction may depend on those
/// operands reading the same dont-care value. For example:
///
/// %vreg1<def> = XOR %vreg2<undef>, %vreg2<undef>
///
/// Any register can be used for %vreg2, and its value doesn't matter, but
/// the two operands must be the same register.
///
bool IsUndef : 1; bool IsUndef : 1;
/// IsEarlyClobber - True if this MO_Register 'def' operand is written to /// IsEarlyClobber - True if this MO_Register 'def' operand is written to
@ -253,6 +268,15 @@ class MachineOperand {
return IsDebug; return IsDebug;
} }
/// readsReg - Returns true if this operand reads the previous value of its
/// register. A use operand with the <undef> flag set doesn't read its
/// register. A sub-register def implicitly reads the other parts of the
/// register being redefined unless the <undef> flag is set.
bool readsReg() const {
assert(isReg() && "Wrong MachineOperand accessor");
return !isUndef() && (isUse() || getSubReg());
}
/// getNextOperandForReg - Return the next MachineOperand in the function that /// getNextOperandForReg - Return the next MachineOperand in the function that
/// uses or defines this register. /// uses or defines this register.
MachineOperand *getNextOperandForReg() const { MachineOperand *getNextOperandForReg() const {

View File

@ -25,6 +25,12 @@ namespace llvm {
/// registers, including vreg register classes, use/def chains for registers, /// registers, including vreg register classes, use/def chains for registers,
/// etc. /// etc.
class MachineRegisterInfo { class MachineRegisterInfo {
const TargetRegisterInfo *const TRI;
/// IsSSA - True when the machine function is in SSA form and virtual
/// registers have a single def.
bool IsSSA;
/// VRegInfo - Information we keep for each virtual register. /// VRegInfo - Information we keep for each virtual register.
/// ///
/// Each element in this list contains the register class of the vreg and the /// Each element in this list contains the register class of the vreg and the
@ -65,7 +71,23 @@ class MachineRegisterInfo {
public: public:
explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); explicit MachineRegisterInfo(const TargetRegisterInfo &TRI);
~MachineRegisterInfo(); ~MachineRegisterInfo();
//===--------------------------------------------------------------------===//
// Function State
//===--------------------------------------------------------------------===//
// isSSA - Returns true when the machine function is in SSA form. Early
// passes require the machine function to be in SSA form where every virtual
// register has a single defining instruction.
//
// The TwoAddressInstructionPass and PHIElimination passes take the machine
// function out of SSA form when they introduce multiple defs per virtual
// register.
bool isSSA() const { return IsSSA; }
// leaveSSA - Indicates that the machine function is no longer in SSA form.
void leaveSSA() { IsSSA = false; }
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
// Register Info // Register Info
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
@ -195,12 +217,25 @@ class MachineRegisterInfo {
void setRegClass(unsigned Reg, const TargetRegisterClass *RC); void setRegClass(unsigned Reg, const TargetRegisterClass *RC);
/// constrainRegClass - Constrain the register class of the specified virtual /// constrainRegClass - Constrain the register class of the specified virtual
/// register to be a common subclass of RC and the current register class. /// register to be a common subclass of RC and the current register class,
/// Return the new register class, or NULL if no such class exists. /// but only if the new class has at least MinNumRegs registers. Return the
/// new register class, or NULL if no such class exists.
/// This should only be used when the constraint is known to be trivial, like /// This should only be used when the constraint is known to be trivial, like
/// GR32 -> GR32_NOSP. Beware of increasing register pressure. /// GR32 -> GR32_NOSP. Beware of increasing register pressure.
///
const TargetRegisterClass *constrainRegClass(unsigned Reg, const TargetRegisterClass *constrainRegClass(unsigned Reg,
const TargetRegisterClass *RC); const TargetRegisterClass *RC,
unsigned MinNumRegs = 0);
/// recomputeRegClass - Try to find a legal super-class of Reg's register
/// class that still satisfies the constraints from the instructions using
/// Reg. Returns true if Reg was upgraded.
///
/// This method can be used after constraints have been removed from a
/// virtual register, for example after removing instructions or splitting
/// the live range.
///
bool recomputeRegClass(unsigned Reg, const TargetMachine&);
/// createVirtualRegister - Create and return a new virtual register in the /// createVirtualRegister - Create and return a new virtual register in the
/// function with the specified register class. /// function with the specified register class.

Some files were not shown because too many files have changed in this diff Show More